

#ifndef FILELIST_H
#define FILELIST_H

#include <tdelistview.h>

#include <cstdint>

#include "conversionoptions.h"

class CDManager;
class TagEngine;
class TagData;
class Options;
class OptionsEditor;
class Config;
class Logger;
class FormatItem; // NOTE DEBUG

class TQPainter;
class TQColorGroup;
class TQSimpleRichText;
class KProgress;
class TDEPopupMenu;
class TDEAction;
class TDEActionCollection;

/**
 * @short The items for the file list
 * @author Daniel Faust <hessijames@gmail.com>
 * @version 0.3
 */
class FileListItem : public TDEListViewItem
{
public:
    /**
     * Constructor
     * @param parent The parent list view
     */
    FileListItem( TDEListView* parent );

    /**
     * Constructor
     * @param parent The parent list view
     * @param after The item, the new item should be placed after
     */
    FileListItem( TDEListView* parent, FileListItem* after );

    /**
     * Destructor
     */
    virtual ~FileListItem();

    virtual void paintCell( TQPainter* p, const TQColorGroup& cg, int column, int width, int alignment );

    //void updateOutputCell();
    //void updateOptionsCell();

    FileListItem* nextSibling() const { return static_cast<FileListItem*>( TDEListViewItem::nextSibling() ); }
    FileListItem* itemAbove() { return static_cast<FileListItem*>( TDEListViewItem::itemAbove() ); }
    FileListItem* itemBelow() { return static_cast<FileListItem*>( TDEListViewItem::itemBelow() ); }
    //FileList* listView() const { return static_cast<FileList*>( TDEListViewItem::listView() ); }

    ConversionOptions options;  // the information we get from the options class for creating the item
    TagData* tags;              // we need to instruct the tagengine to read the tags from the file!
                                // and the user can change them!
    TQString fileName;           // just the _name_ of the file
    TQString mimeType;           // the mime type of the file
    TQString fileFormat;         // just the _format_ of the file (for easier use)
    TQString url;                // the original input file name string
    bool converting;            // is this item being converted at the moment?
    bool local;                 // is this file a local one?
    int track;                  // the number of the track, if it is on an audio cd
                                // if it is lower than 0, it isn't an audio cd track at all
    TQString device;             // the device of the audio cd
    bool ripping;               // is this track currently being ripped?

    float time;                 // the duration of the track, used for the calculation of the progress bar
    TQString notify;             // execute this command, when the file is converted
};

/**
 * @short The file list
 * @author Daniel Faust <hessijames@gmail.com>
 * @version 0.3
 */
class FileList : public TDEListView
{
    TQ_OBJECT
  
public:
    /**
     * Constructor
     * @param parent The parent widget
     * @param name The name of the file list
     */
    FileList( CDManager*, TagEngine*, Config*, Options*, Logger*, TQWidget *parent = 0, const char* name = 0 );

    /**
     * Destructor
     */
    virtual ~FileList();

    FileListItem* firstChild() const { return static_cast<FileListItem*>( TDEListView::firstChild() ); }
    FileListItem* lastItem() const { return static_cast<FileListItem*>( TDEListView::lastItem() ); }

    int columnByName( const TQString& name );
    void updateItem( FileListItem* item );

    bool queueEnabled() { return queue; }

    void setNotify( const TQString& cmd ) { notify = cmd; }

protected:
    virtual bool acceptDrag( TQDropEvent *e ) const;

private:
    /** Lists all file in a directory and adds them to the file list, if @p fast is false. The number of listed files is returned */
    int listDir( const TQString& directory, TQStringList filter, bool recursive = true, bool fast = false, int count = 0 );

    /** A progressbar, that is shown, when a directory is added recursive */
    KProgress* pScanStatus;

    void convertNextItem();

    void viewportPaintEvent( TQPaintEvent* );
    void viewportResizeEvent( TQResizeEvent* );

    void debug(); // NOTE DEBUG
    TQString debug_params( ConversionOptions conversionOptions, FormatItem* formatItem ); // NOTE DEBUG

    TQSimpleRichText* bubble;

    /** The context menu for editing or starting the files */
    TDEPopupMenu* contextMenu;

    TDEActionCollection* actionCollection;
    TDEAction* edit;
    TDEAction* start;
    TDEAction* stop;
    TDEAction* remove;
    TDEAction* paste;

    CDManager* cdManager;
    TagEngine* tagEngine;
    OptionsEditor* optionsEditor;

    Options* options;
    Config* config;
    Logger* logger;

    TQValueList<FileListItem*> selectedFiles;

    bool queue;

    /**
     * A command that should be executed after the conversion of a file is complete
     * %i will be replaced by the input file path
     * %o "    "  "        "  "   output "   "
     */
    TQString notify;

private slots:
    /*
     * The user clicked somewhere into the list view (e.g. the link in the bubble)
     */
//     void clickedSomewhere( TQListViewItem*, const TQPoint&, int );

    /**
     * We'll recive a signal, when we should show the context menu
     * @p item The item, that's context menu should be shown
     * @p point The position of the click (start position of the context menu)
     */
    void showContextMenu( TQListViewItem* item, const TQPoint& point, int );

    /**
     * Remove selected items from the file list
     */
    void removeSelectedItems();

    /**
     * Add selected items to the conversion list
     */
    void convertSelectedItems();

    /**
     * Stop the conversion of all selected items
     */
    void stopSelectedItems();

    void columnResizeEvent( int, int, int );
    void slotDropped( TQDropEvent*, TQListViewItem*, TQListViewItem* ); // NOTE rename?

public slots:
    void addFiles( TQStringList, FileListItem* after = 0, bool enabled = false ); // NOTE const TQStringList& ?
    void addDir( const TQString&, const TQStringList& filter = "", bool recursive = true );
    void addTracks( const TQString& device, TQValueList<int> );
    void addDisc( const TQString& device );
    /**
     * The conversion of an item has finished and the state is reported ( 0 = ok, -1 = error, 1 = aborted )
     */
    void itemFinished( FileListItem*, int );
    void rippingFinished( const TQString& device );
    void showOptionsEditorDialog();
    void selectPreviousItem();
    void selectNextItem();
    void itemsSelected();
    //void moveOptionsEditor( int x, int y );
    void startConversion();
    void stopConversion();
    void continueConversion();
    void killConversion();

    void load( bool autosave = false );
    void save( bool autosave = false );

signals:
    void convertItem( FileListItem* );
    void stopItem( FileListItem* );
    void editItems( TQValueList<FileListItem*> );
    void setPreviousItemEnabled( bool );
    void setNextItemEnabled( bool );
    //void moveEditor( int x, int y );
    void fileCountChanged( int );
    void startedConversion();
    void stopClicked();
    void continueClicked();
    void stoppedConversion();

    void increaseTime( float );
    void decreaseTime( float );
    //void countTime( float );
    //void setTime( float );
    void finished( float );
};

inline TQColor shiftColorToRed(TQColor c, uint8_t strength) {
    int r = c.red() + strength * (255 - c.red()) / 255;
    int g = c.green() * (255 - strength) / 255;
    int b = c.blue() * (255 - strength) / 255;

    return TQColor(r, g, b);
}

inline TQColor shiftColorToYellow(TQColor c, uint8_t strength) {
    int r = c.red() + strength * (255 - c.red()) / 255;
    int g = c.green() + strength * (255 - c.green()) / 255;
    int b = c.blue() * (255 - strength) / 255;

    return TQColor(r, g, b);
}

#endif // FILELIST_H
