#include <iostream>
#include <string>

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/regex.hpp>

#include "PhotoCompressArchiver.hh"

// Alias the namespace for readability
namespace bpo = boost::program_options;

void header()
{
    std::cout << BOLD << "Photo Compress Archiver -- " << version << "\n" << ENDC;
    std::cout << "    Copyright 2017 - David Sorber\n";
    std::cout << "    >>> Utilizing packJPG by Matthias Stirner\n" << std::endl;    
}

void usage(char** argv)
{
    // Remove leading "./" if it exits
    char* app_name = argv[0];
    if (argv[0][0] == '.' && argv[0][1] == '/')
    {
        char* app_name = &argv[0][2];
    }
    
    header();
    std::cout << "USAGE: " << app_name << " [-hkd] <file path>\n\n";
    std::cout << "Positional arguments:\n";
    std::cout << "  <file path>           path in which to recursively look "
              << "for input files\n\n";
    std::cout << "General options:\n";
    std::cout << "  -h [ --help ]         display this help message\n";
    std::cout << "  -d [ --decompress ]   find '*.pjg' files and decompress them\n";
    std::cout << "  -k [ --keep-orig ]    keep original files; don't delete them\n";
    std::cout << std::endl;
}


int main(int argc, char** argv)
{
    bpo::variables_map general_opts_vm;
    
    try
    {
        // General options
        bpo::options_description general_opts("General options");
        general_opts.add_options()
            ("help,h", "display this help message")
            ("decompress,d", "find '*.pjg' files and decompress them")
            ("keep-orig,k", "keep orignal files")
            ("file_path", "path in which to recursively look for input files")
        ;

        // Positional arguments
        bpo::positional_options_description pos_opts; 
        pos_opts.add("file_path", 1);
        
        // Parse general/positional options
        bpo::store(bpo::command_line_parser(argc, argv).options(general_opts)
                   .positional(pos_opts).allow_unregistered().run(), 
                   general_opts_vm);
        
        
        // Display help if the option is listed or if no arguments are provided
        if (general_opts_vm.count("help") || (argc == 1)) 
        {
            usage(argv);
            return 0;
        }
    }    
    catch (std::exception& e) 
    {
        std::cerr << BOLD << RED << "ERROR: " << ENDC << e.what() << "\n";
        return -1;
    }
    
    
    // Make a copy of the file search path for passing into the object below
    std::string search_path(general_opts_vm["file_path"].as<std::string>());
    
    // Make sure that path specified actually exists before proceeding
    if (! bfs::exists(search_path))
    {
        std::cerr << BOLD << RED << "ERROR: " << ENDC << "the path \"" 
                  << search_path << "\" does not exist" << std::endl;
        return -2;
    }
    
    // Display header and 
    header();    
    uint32_t num_cores = std::thread::hardware_concurrency();
    std::cout << "    [" << num_cores << " cores detected]\n";
    
    // Decode/store decompress option
    bool decompress = false;
    if (general_opts_vm.count("decompress"))
    {
        decompress = true;
        std::cout << "    decompress mode     => ON\n";
    }

    // Decode/store keep-orig option
    bool keep_orig = false;
    if (general_opts_vm.count("keep-orig"))
    {
        keep_orig = true;
        std::cout << "    keep original files => ON\n";
    }
    
    std::cout << std::endl;
    
    auto pca = new PhotoCompressArchiver(search_path, num_cores, decompress, 
                                         keep_orig);
    pca->execute();
    delete pca;
    
    return 0;
}
