//
//  mh5000
//
//  Copyright (c) 2018 Michael Heras
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307,
//  USA.
//
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <random>
#include <iterator>
#include <dirent.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctime>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h> //type dir/file
#include <stdlib.h> //exit
#include </usr/include/Imlib2.h> //Imlib_Load_Error
#include "img.h"
#include "options.h"
#include "files.h"

options opts;

using namespace boost::filesystem;

namespace filesys = boost::filesystem;

struct recursive_directory_range
{
    typedef recursive_directory_iterator iterator;
    recursive_directory_range(path p) : p_(p) {}

    iterator begin() { return recursive_directory_iterator(p_); }
    iterator end() { return recursive_directory_iterator(); }

    path p_;
};
size_t loadFiles(std::vector<std::string> &mylist , boost::filesystem::path p)
{

  for (auto it : recursive_directory_range(p))
  {
      //convert char to string
      std::stringstream newStringPath;
      newStringPath << it;
      std::string myStringPath = newStringPath.str();

    if (  checkFileExt(getFileExt(myStringPath)) == 1 )
    {
         // Remove all double-quote characters
        myStringPath.erase(
        remove( myStringPath.begin(), myStringPath.end(), '\"' ),
        myStringPath.end() );

        mylist.push_back( myStringPath );
    }
 }
 return 0;
 }
//not being used
void put_in_one_file (std::vector<std::string> &mylist , char * f)
{

    std::string f2 = f;
    mylist.push_back( f2 );
}

std::string getFileExt(const std::string& s)
{
    size_t i = s.rfind('.', s.length());
    try
    {
        if (i != std::string::npos)
        {
            std::string lext = (s.substr(i+1, s.length() - i));
            return (lext.erase(lext.size() - 1));
        }
    }
    catch(...)
    {
        std::cout<<"Exception Caught!"<<std::endl;
        std::cout<<s<<std::endl;
    }
   return("");
}
std::string getFileExt(const std::string& s, int len)
{
    size_t i = s.rfind('.', s.length());
    try
    {
        if (i != std::string::npos)
        {
            std::string lext = (s.substr(i+1, s.length() - i));
            return (lext.erase(lext.size() - len));
        }
    }
    catch (...)
    {
        std::cout<<"Exception Caught!!"<<std::endl;
        std::cout<<s<<std::endl;
    }
   return("");
}
size_t checkFileExt(std::string extension)
{
    std::vector <std::string> extensions = {"jpg", "JPG", "png", "bmp", "jpeg", "gif", "xpm"};

	for ( unsigned int i = 0; i < extensions.size(); i++)
        if (extension == extensions[i]){
            return 1;
        }
    return 0;
}

std::string get_random_file()
{
	int min=0, max=opts.dfile.size() - 1;

	return ( opts.dfile.at( ( getRany(min,max) ) ) );
}


std::string walk_down()
{ std::cout<<"walk down"<<std::endl;
	for (int i = 0; i < 1; i++)
	{
		if (opts.leftoff == opts.dfile.size() - 1)
		{
			opts.leftoff = 0;
			return ( opts.dfile.at(opts.leftoff) );
		}
		else
		{
			opts.leftoff++;
			return ( opts.dfile.at(opts.leftoff) );
		}
	}
	return ( opts.dfile.at(opts.leftoff) );
}


void sort_V()
{
	std::sort(opts.dfile.begin(), opts.dfile.end(), compareNoCase);
}
// Comparison; not case sensitive.
bool compareNoCase (std::string first, std::string second)
{
  unsigned long int  i = 0;
  while ((i < first.length()) && (i < second.length()))
  {
    if (tolower (first[i]) < tolower (second[i])) return true;
    else if (tolower (first[i]) > tolower (second[i])) return false;
    i++;
  }

  if (first.length() < second.length()) return true;
  else return false;
}

int Load_single_Image()
{
    Imlib_Load_Error err;

    imgdata.image = imlib_load_image_with_error_return(opts.path, &err);

    if (err)
    {
        std::cout<<"Bad Image: "<<opts.path<<std::endl;

        return 1;
    }
    return 0;
}

void load_image_err(void)
{
	Imlib_Load_Error err;
	std::string newFilename = get_file_name();
	const char* filename = newFilename.c_str();

	if(filename == NULL)
	{
		std::cout<<"File null"<<std::endl;
		exit(1);
    }

  imgdata.image = imlib_load_image_with_error_return(filename, &err);
 // print loaded filename to stdout
 if(img.printlistintake == 3)
    std::cout<<filename<<std::endl;

	if (err)
	{

	//spit out image path and name
	std::cout<< "Bad Image: "<<filename<<std::endl;
	  // get next image
	   load_image_err();


	}
	std::cout<<filename<<std::endl;
}

std::string get_file_name(void)
{ //std::cout<<"get file name in "<<std::endl;
   	if( img.set_randomize == 1)
    { //std::cout<<"get file name 1 "<<std::endl;
		return ( get_random_file() );
    }

    if ( (signed)img.file_number >= 0 )
	{ //std::cout<<"get file name 2 "<<img.file_number<<std::endl;
        return ( opts.dfile.at(img.file_number) );
    }
    else if ( (signed)img.file_number >= 0 && img.file_number > opts.dfile.size() )
    {
        std::cout<<"Image number "<<img.file_number<<" out of range."<<std::endl;
        std::cout<<"Range is 0 to "<<opts.dfile.size() - 1<< std::endl;
        set_oops_color();
        Load_OOPs_Image();
        exit(1);
    }
    //std::cout<<"get file name 3 "<<std::endl;
    return (walk_down());
}

size_t getRany(int min, int max)
{
	std::random_device seed;
	std::mt19937 gen(seed());
    std::uniform_int_distribution<int> dist(min, max);
	return ( dist(gen) );
}

int loadFiles_FromList(std::vector<std::string> &mylist, std::string file)
{
   // std::cout<<"loadFiles_FromList"<<std::endl;

    std::ifstream myfile(file.c_str());
    if (myfile.is_open())
    {
        std::string line;

        while ( getline (myfile,line) )
        {
             if (  checkFileExt(getFileExt(line, 0) ) == 1 )
                mylist.push_back( line );
        }
        myfile.close();
        return 0;
    }
    else
        std::cout<<" Not able to open file"<<"\n";
    return 1;
}

void Print_FromFileList(std::vector<std::string> &aList)
{
      for ( auto i: aList )
    {
        std::cout << i <<"\n";
    }
}

void writeToFile(std::vector<std::string> &mylist, std::string file)
{
    std::ofstream theFile (file);
    if (theFile.is_open())
    {
        for ( auto i : mylist)
        {
            theFile << i << "\n";
        }
        theFile.close();
    }
    else
        std::cout<<"Unable to open output file "<<file<<std::endl;
}

bool checkIfFile(std::string filePath)
{
	try {
		// Create a Path object from given path string
		filesys::path pathObj(filePath);
		// Check if path exists and is of a regular file
		if (filesys::exists(pathObj) && filesys::is_regular_file(pathObj))
			return true;
	}
	catch (filesys::filesystem_error & e)
	{
		std::cerr << e.what() << std::endl;
	}
	return false;
}

bool checkIfDirectory(std::string filePath)
{
	try {
		// Create a Path object from given path string
		filesys::path pathObj(filePath);
		// Check if path exists and is of a directory file
		if (filesys::exists(pathObj) && filesys::is_directory(pathObj))
			return true;
	}
	catch (filesys::filesystem_error & e)
	{
		std::cerr << e.what() << std::endl;
	}
	return false;
}

void randomizeFiles()
{

    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(opts.dfile.begin(), opts.dfile.end(), g);

}
