#ifndef MFILER2_DIRWND
#define MFILER2_DIRWND

extern "C" {
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
}

struct sFile{
    char mName[PATH_MAX];
    struct stat mStat;
    struct stat mLStat;
    bool mMark;

    sFile(char* name, struct stat* stat_, struct stat* lstat_, bool mark)
    {
        strcpy(mName, name);
        mStat = *stat_;
        mLStat = *lstat_;
        mMark = mark;
    }
};

struct sDirInfo {
    char mPath[512];
    int mScrollTop;
    int mCursor;
};

class cDirWnd {
    char mPath[PATH_MAX];    // last char is '/'
    char mPathBefore[PATH_MAX];
    hash_obj* mMarkFiles;

    vector_obj* mFiles;
    
    int mScrollTop;
    int mCursor;

    char mMask[1024];
    
    list_obj* mDirStack;
   
    static BOOL sort_name(void* left, void* right);
    static BOOL sort_name_reverse(void* left, void* right);
    static BOOL sort_ext(void* left, void* right);
    static BOOL sort_ext_reverse(void* left, void* right);
    static BOOL sort_size(void* left, void* right);
    static BOOL sort_size_reverse(void* left, void* right);
    static BOOL sort_time(void* left, void* right);
    static BOOL sort_time_reverse(void* left, void* right);
    static BOOL sort_user(void* left, void* right);
    static BOOL sort_user_reverse(void* left, void* right);
    static BOOL sort_group(void* left, void* right);
    static BOOL sort_group_reverse(void* left, void* right);

    static const int kMaxYMinus = 4;

    void read();
    bool check_path(char* new_path);
public:
    cDirWnd(char* path, bool active);
    ~cDirWnd();

    static void Init();
    static void Final();

    static void ReadHistory();
    static void SaveHistory();

    static void* operator new(size_t size) { return MALLOC(size); }
    static void operator delete(void* p) { FREE(p); }

    static const int kDirStackSize = 500;
    static bool gRemainMarks;

    /// properties ///
    bool mActive;
   
    enum eSortKind { kName, kNameReverse, kExt, kExtReverse, kSize, kSizeReverse, kTime, kTimeReverse, kUser, kUserReverse, kGroup, kGroupReverse, kSortMax };
    static eSortKind gSortKind;

    static char* kSortName[cDirWnd::kSortMax];

    enum eViewOption { kAll, kOneDir, kOneDir2, kOneDir3, kOneDir5 };
    static eViewOption gViewOption;
    static bool gViewNameOnly;

    static bool gSortDirUp;
    
    vector_obj* Files() { return mFiles; }
    sFile* CursorFile();
    sFile* File(int num);
    char* Path() { return mPath; }
    VALUE MarkFiles();
    ALLOCATED string_obj* MarkFilesSQuote();
    int MarkFileNum();
    int MarkFileSize();

    bool Marking();

    bool IsLeftDir();
    bool IsRightDir();

    /// methods ///
    int Cursor();
    int CursorMax();
    int CursorX();
    int CursorY();
    int CursorMaxX();
    int CursorMaxY();
    void MoveCursor(int index);
    int ScrollTop();
    void SetScrollTop(int index);
    
    void Mark();
    void Mark2(int index);
    void Mark3(int index);
    void MarkAll();
    void MarkAllFiles();
    void MarkOff(int index);
    void ResetMarks();
    
    void Activate(cDirWnd* current);
   
    void Move(char* path);        // last char don't have to be '/'
    void MoveBack();

    void PushDir(int num, char* path, int scroll_top, int cursor);
    void PushFrontDir();
    void PushBackDir();
    void PopDir();
    void SelectDir();

    static void CloseTab(int num);
    void UpTab(int num);
    static int TabMax();
    static void TabNew(char* path);
    static char* TabPath(int num);
   
    void Sort();
    void View();
    
    void SelectDirView();
    void SelectDirInput(int meta, int key);

    void Reread();
    bool ChangeMask(char* mask);
};

extern cDirWnd* ActiveDir();
extern cDirWnd* SleepDir();
extern bool gSelectDir;

#endif
