/*
 * File Name: images_scanner.h
 */

/*
 * This file is part of uds-plugin-images.
 *
 * uds-plugin-images 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.
 *
 * uds-plugin-images 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, see <http://www.gnu.org/licenses/>.
 */

/**
 * Copyright (C) 2008 iRex Technologies B.V.
 * All rights reserved.
 */

#ifndef _IMAGES_SCANNER_H_
#define _IMAGES_SCANNER_H_

#include <vector>
#include <string>

#include <glib.h>

#include "plugin_type.h"

namespace images
{
    typedef enum
    {
        BY_FILEPATH = 0,
        BY_FILENAME,
        BY_EXT,
        BY_DATE,
        BY_SIZE,
    }SortType;

    struct Image
    {
        std::string path;
     
        // MetaData
        int width;     // '-1' means need to calculate.
        int height;    // '-1' means need to calculate.
        bool is_rotation_calculated;    // true/false means rotation is/is-not calculated
        PluginRotationDegree rotation;  // 

        std::string sort_field;
    };

    typedef Image *ImagePtr;
    typedef std::vector<ImagePtr> Images;
    typedef std::vector<ImagePtr>::iterator ImagesIter;

    /**
     * @brief  : Scan all the images in the formats supported by gdk_pixbuf
     *           under the input directory 
     *           or the directory which the input filename is located in.
     *           It also supports the option of scanning recursively or not.
     */
    class ImagesScanner
    {
        public:
            /**
             * @brief Construct a 'ImagesScanner'.
             */
            ImagesScanner(void);
            ~ImagesScanner(void);

        public:
            bool is_image(const std::string & filename);
            
            static bool get_size(const std::string & filename,
                                 int * width, int * height);             

            static void get_original_rotation(const std::string & filename, 
                                              PluginRotationDegree & rotation);

            /**
             * @brief Set the filename or directory to scan.
             * @param filename 
             * @param to_scan_dir Scan or not scan the directory where the filename is in.
             * @param recursive_flag Scan recursively or not.
             * @param sort_type Sort by date, size, etc.
             * @param sort_ascending Sort by ascending or descending.
             * @return Get the index of the current active image.
             *        The current active image is the input filename.
             *        Or if the input filename is directory, 
             *        the active image is the first image file found.
             */
            int scan_images(const std::string & filename,
                            bool to_scan_dir,
                            bool recursive_flag,
                            SortType sort_type,
                            bool sort_ascending,
                            Images & results);
        
       private:
            void get_supported_extnames(void);

            bool check_extname(const std::string & filename);

            /**
             * @brief Set the filename or directory to scan.
             * @param filename: the image filepath or dir
             */
            void set_filename(const std::string & filename);

            void append_dir_separator(std::string & dirpath);
            
            /**
            * @brief Scan the dir, check each file by using filter.
            *        If yes, add the filename into the results list.
            *        Meanwhile set the current activate image.
            */
            void scan_dir(const std::string & dirpath, 
                          Images & results);

            void sort_images(Images & results,
                             SortType sort_type, 
                             bool sort_ascending);

            static bool greater_by_filepath(Image * a, Image * b); 
            static bool greater_by_filename(Image * a, Image * b); 
            static bool greater_by_ext(Image * a, Image * b); 
            static bool greater_by_date(Image * a, Image * b); 
            static bool greater_by_size(Image * a, Image * b); 

            static bool less_by_filepath(Image * a, Image * b); 
            static bool less_by_filename(Image * a, Image * b); 
            static bool less_by_ext(Image * a, Image * b); 
            static bool less_by_date(Image * a, Image * b); 
            static bool less_by_size(Image * a, Image * b); 

        private:
            std::string filepath; ///< the original input file path
            bool recursive;       ///< scan recursively or not
            bool isdir;           ///< the input filename is directory
            std::string dir;      ///< the directory to scan

            typedef std::vector<std::string> ExtNames;
            typedef std::vector<std::string>::iterator ExtNamesIter;
            ExtNames extnames; ///<  stored in format doc jpg bmp png etc.

            int  active;        ///< the index of the active image
    };

} // namespace image

#endif // _IMAGES_SCANNER_H_


