/*
    wmimagedock

  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 <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <cctype> //isdigit
#include <X11/extensions/shape.h>
#include <Imlib2.h>
#include "wmimagedock.hpp"
#include "imagefiles.hpp"

using namespace std;

void WMWindowDock::parseCmLine(int argc, char **argv)
{
    if (argc > 2)
    {
        for ( int i = 1; i <  argc; i++)
        {
            if (!strcmp(argv[i], "-t") )
            {
                if ( argv[i+1] == NULL)
                {
                    usage(argv);
                    exit(0);
                }
               if ( (stime = int_or_ch(argv[++i]) )  == 7)
               {
                   usage(argv);
                   exit(0);

               }
            }
            else if (!strcmp(argv[i], "-m") )
            {

                if (!strcmp( argv[++i], "a"))
                {
                    setMode(A);
                    continue;
                }
                else if (!strcmp(argv[i], "b"))
                {
                    setMode(B);
                    continue;
                }
                else if (!strcmp( argv[i] , "c"))
                {
                    setMode(C);
                    continue;
                }
                else
                {
                    usage(argv); exit(1);
                }
            }
            else if (!strcmp(argv[i], "-c1") )
            {
                setCommandOne(argv[++i]);
            }
            else if (!strcmp(argv[i], "-c2") )
            {
                setCommandTwo(argv[++i]);
            }
            else if (!strcmp(argv[i], "-e"))
            {
                filename = argv[++i];
            }
            else if (!strcmp(argv[i], "-r"))
            {
                isRandom = true;
            }
            else if (!strcmp(argv[i], "-o"))
            {
                isOrdered = true;
            }
            else if (!strcmp(argv[i], "-dz") )
            {
				DockSize = atoi(argv[++i]);
				isize = (DockSize - 3);
			}
            else if (!strcmp(argv[i], "-h") )
            {
                usage(argv);
                exit(0);
            }
        }
    } // end if
    else
    {
        usage(argv); exit(0);
    }
}
void WMWindowDock::setMode(int s)
{
    mode = s;
}
void WMWindowDock::filesGetter(char **argv)
{
    if (filename.empty() )
    {
        usage(argv);
        exit(1);
    }
    if ( checkFileExt ( getFileExt(filename, 0) ) == 1 )
    {
        std::cout<<"\n"<<"Has to be file containing list of images"<<"\n"
        <<"with absolute paths, or, a directory containing images."<<std::endl
        <<"Not a Single Image."<<std::endl<<std::endl;
        exit(1);
    }
    else if (  checkIfDirectory(filename)  )
    {
        std::cout<<"Loading Files ..."<<std::endl;
      if (  loadFiles(opts.dfile, filename) != 1 )
        std::cout<<"Done."<<std::endl;
        else
        {
            usage(argv);
            exit(1);
        }
    }
    else
    {
        std::cout<<"Loading from List ..."<<std::endl;
            if (loadFiles_FromList(opts.dfile, filename) == 1)
            {
                cout<<filename<<endl;
                exit(1);
            }
        std::cout<<"Done."<<std::endl;
    }
}

void WMWindowDock::openXup(int argc, char **argv)
{
    char *displayName = NULL;

     // Open display
    if ((mDisplay = XOpenDisplay(displayName)) == NULL)
    {
      std::cerr << APPNAME << ": could not open display " << displayName << std::endl;
      exit(0);
    }

    // Get root window
    mRoot = RootWindow(mDisplay, DefaultScreen(mDisplay));

    // Create windows
    mAppWin = XCreateSimpleWindow(mDisplay, mRoot, 1, 1, DockSize, DockSize, 1, 1 , 0);
    mIconWin = XCreateSimpleWindow(mDisplay, mAppWin, 0, 0, isize, isize, 0, 0, 0);
    gc=XCreateGC(mDisplay, mIconWin, 0,0);
    //create display pixmap
    screen = XDefaultScreen(mDisplay);
    depth = DefaultDepth(mDisplay,screen );
    pix = XCreatePixmap(mDisplay, mRoot, DockSize, DockSize, depth);

    // Set classhint
    // to conform to the C char* agasint
    // c++ requiring a const char*
    classHint.res_name =  const_cast<char*>(wInstanceName);
    classHint.res_class = const_cast<char*>(wClassName);
    XSetClassHint(mDisplay, mAppWin, &classHint);


    XSelectInput(mDisplay, mAppWin, ButtonPressMask | ExposureMask | ButtonReleaseMask |
            PointerMotionMask | StructureNotifyMask);
    XSelectInput(mDisplay, mIconWin, ButtonPressMask | ExposureMask | ButtonReleaseMask |
            PointerMotionMask | StructureNotifyMask );


    // Create delete atom
    deleteWindow = XInternAtom(mDisplay, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(mDisplay, mAppWin, &deleteWindow, 1);
    XSetWMProtocols(mDisplay, mIconWin, &deleteWindow, 1);

    // Set windowname
    XStoreName(mDisplay, mAppWin, APPNAME);
    XSetIconName(mDisplay, mAppWin, APPNAME);

    // Set sizehints
    sizeHints.flags = USSize  | USPosition;
    sizeHints.x = 0;
    sizeHints.y = 0;
    XSetWMNormalHints(mDisplay, mAppWin, &sizeHints);

    // Set wmhints
    wmHints.initial_state = WithdrawnState;
    wmHints.icon_window = mIconWin;
    wmHints.icon_x = 0;
    wmHints.icon_y = 0;
    wmHints.window_group = mAppWin;
    wmHints.flags = StateHint | IconWindowHint | WindowGroupHint | IconPositionHint ;
    XSetWMHints(mDisplay, mAppWin, &wmHints);

    // Set command
    XSetCommand(mDisplay, mAppWin, argv, argc);
    XMapWindow(mDisplay, mAppWin);
    XMapWindow(mDisplay, mIconWin);
    XClearWindow(mDisplay,mAppWin);
    XClearWindow (mDisplay,mIconWin);
    XFlush (mDisplay);
    XSync(mDisplay, False);
}
void WMWindowDock::DisplayImage()
{
    visual = DefaultVisual(mDisplay, DefaultScreen(mDisplay));
    imlib_context_set_dither(1);
    imlib_context_set_display(mDisplay);
    imlib_context_set_visual(visual);
    buffer = imlib_create_image(isize, isize);
    imlib_context_set_blend(1);
    if ( load_err_image( get_file_name( getObject()  ) ) == 1 )
    {
        load_err_image( get_file_name( getObject() ) );
    }
    imlib_context_set_image(image);
    int w = imlib_image_get_width();
    int h = imlib_image_get_height();
    imlib_context_set_image(buffer);
    if (buffer)
    {
        imlib_blend_image_onto_image(buffer, 0, 0, 0,w,h,0,0,isize,isize );
        imlib_context_set_image(image);
        imlib_context_set_drawable(pix);
        imlib_render_image_on_drawable_at_size(0, 0, isize,isize);
        imlib_free_image();
        XSetWindowBackgroundPixmap (mDisplay, mIconWin, pix);
        XClearWindow(mDisplay, mAppWin);
        XClearWindow (mDisplay, mIconWin);
        XFlush (mDisplay);
        XSync (mDisplay, False);
    }
}
void WMWindowDock::transverseImage()
{
    visual = DefaultVisual(mDisplay, DefaultScreen(mDisplay));
    imlib_context_set_dither(1);
    imlib_context_set_display(mDisplay);
    imlib_context_set_visual(visual);
    buffer = imlib_create_image(isize, isize);
    imlib_context_set_blend(1);
    if ( load_err_image( transverseList() ) == 1 )
    {
        load_err_image( transverseList() );
    }
    imlib_context_set_image(image);
    int w = imlib_image_get_width();
    int h = imlib_image_get_height();
    imlib_context_set_image(buffer);
    if (buffer)
    {
        imlib_blend_image_onto_image(buffer, 0, 0, 0,w,h,0,0,isize,isize );
        imlib_context_set_image(image);
        imlib_context_set_drawable(pix);
        imlib_render_image_on_drawable_at_size(0, 0, isize,isize);
        imlib_free_image();
        XSetWindowBackgroundPixmap (mDisplay, mIconWin, pix);
        XClearWindow(mDisplay, mAppWin);
        XClearWindow (mDisplay, mIconWin);
        XFlush (mDisplay);
        XSync (mDisplay, False);
    }
}
void WMWindowDock::reverseImage()
{
    visual = DefaultVisual(mDisplay, DefaultScreen(mDisplay));
    imlib_context_set_dither(1);
    imlib_context_set_display(mDisplay);
    imlib_context_set_visual(visual);
    buffer = imlib_create_image(isize, isize);
    imlib_context_set_blend(1);
    if ( load_err_image( transposeList() ) == 1 )
    {
        load_err_image( transposeList() );
    }
    imlib_context_set_image(image);
    int w = imlib_image_get_width();
    int h = imlib_image_get_height();
    imlib_context_set_image(buffer);
    if (buffer)
    {
        imlib_blend_image_onto_image(buffer, 0, 0, 0,w,h,0,0,isize,isize );
        imlib_context_set_image(image);
        imlib_context_set_drawable(pix);
        imlib_render_image_on_drawable_at_size(0, 0, isize,isize);
        imlib_free_image();
        XSetWindowBackgroundPixmap (mDisplay, mIconWin, pix);
        XClearWindow(mDisplay, mAppWin);
        XClearWindow (mDisplay, mIconWin);
        XFlush (mDisplay);
        XSync (mDisplay, False);
    }
}
void  WMWindowDock::setBuffer(Imlib_Image im)
{
    buffer = im;
}
int WMWindowDock::load_err_image(std::string path)
{
    Imlib_Load_Error err;
    const char *fpath = path.c_str();
    //send filename to stdout
    std::cout<<fpath<<std::endl;
    setLoadedFileName(path);
    //check function to see if it is working.
    image = imlib_load_image_with_error_return(fpath, &err);

    if (err)
    {
        std::cout<<"Bad Image: "<<fpath<<std::endl;

        return 1;
    }
    return 0;
}
void WMWindowDock::usage(char **argv)
{

    std::cout<<"To load images use,"<<std::endl
    <<"a directory with image files,"<<std::endl
    <<"or a file listing with absolute path and image."<<std::endl
    <<"Usage of a file dramatically increases load time."<<std::endl
    <<"Easy way to create a file containing the images."<<std::endl<<std::endl
    <<"find /path -type f >> myImages"<<std::endl<<std::endl
    <<argv[0]<<" -e : either a directory or a file."<<std::endl
    <<argv[0]<<" -t : delay time in seconds."<<std::endl
    <<argv[0]<<" -r : display images in random order."<<std::endl
    <<argv[0]<<" -o : display images in ordered list."<<std::endl
    <<argv[0]<<" -c1 : cmd to be executed. Double left click."<<std::endl
    <<argv[0]<<" -c2 : cmd to be executed. Double right click."<<std::endl
    <<"MOdes of operation: a | b | c"<<std::endl<<std::endl
    <<argv[0]<<" -m a | b | c"<<std::endl
    <<"a is for default operation of cycling images with two double click"<<std::endl
    <<"  commands for execution of exteral programs."<<std::endl
    <<"b mouse wheel to change images, forward, and backwards. Left double click"<<std::endl
    <<"  sets current image to desktop background. Right double click tiles background."<<std::endl
    <<"c auto cycles the images and if you see one you like double left click."<<std::endl
    <<"  sets it as the background image. Double right click titles Background."<<std::endl
    <<argv[0]<<"-dz <size>"<<std::endl
    <<"It is a single number to give the size of the square dockapp"<<std::endl
    <<"Default size is 64x64"<<std::endl
    <<argv[0]<<" -h : Display usage."<<std::endl<<std::endl
    <<APPNAME<<" -t 30 -r -e /path/to/image directory"<<std::endl
    <<APPNAME<<" -c1 firefox -e ~/myImages -r -t 30"<<std::endl
    <<APPNAME<<" -e /path -m b -c2 command"<<std::endl
    <<APPNAME<<" -e path -m b -dz 120"<<std::endl
    <<"Can have multiple instances of this app running at same time."<<std::endl
    <<"Defaults to mode setting 'a' without selecting it."<<std::endl<<std::endl
    <<APPNAME<<" v"<<VERSION<<" "<<COPYRIGHT<<" "<<AUTHOR<<std::endl<<std::endl;
}
