#include "common.h"

cDirWnd* ActiveDir()
{
    if(gLDir->mActive)
        return gLDir;
    else
        return gRDir;
}

cDirWnd* SleepDir()
{
    if(!gLDir->mActive)
        return gLDir;
    else
        return gRDir;
}

///////////////////////////////////////////////////////////////////////////////
// 拡張子同一のファイルをマーク中か？
///////////////////////////////////////////////////////////////////////////////
bool cDirWnd::IsSameExtensionMarked(char* result)
{
    if(!Marking()) return false;

    strcpy(result, "");
    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);
        if(file->mMark) {
            char* tmp = extname(file->mName);
            
            if(strcmp(result, "") == 0) {
                strcpy(result, tmp);
            }
            else {
                if(gExtensionICase) {
                    if(strcasecmp(result, tmp) != 0) {
                        strcpy(result, "");
                        return false;
                    }
                }
                else {
                    if(strcmp(result, tmp) != 0) {
                        strcpy(result, "");
                        return false;
                    }
                }
            }

            free(tmp);
        }
    }

    return true;
}

///////////////////////////////////////////////////////////////////////////////
// ディレクトリをマーク中
///////////////////////////////////////////////////////////////////////////////
bool cDirWnd::IsDirectoryMarked()
{
    if(!Marking()) return false;

    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);
        if(file->mMark) {
            if(!S_ISDIR(file->mStat.st_mode)) {
                return false;
            }
        }
    }
    
    return true;
}

///////////////////////////////////////////////////////////////////////////////
// 実行ファイルをマーク中
///////////////////////////////////////////////////////////////////////////////
bool cDirWnd::IsExecutiveFileMarked()
{
    if(!Marking()) return false;

    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);
        if(file->mMark) {
            if(!(file->mStat.st_mode&S_IXUSR) && !(file->mStat.st_mode&S_IXGRP) && !(file->mStat.st_mode&S_IXOTH))
            {
                return false;
            }
        }
    }
    
    return true;
}

///////////////////////////////////////////////////////////////////////////////
// リンクをマーク中
///////////////////////////////////////////////////////////////////////////////
bool cDirWnd::IsLinkMarked()
{
    if(!Marking()) return false;

    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);
        if(file->mMark) {
            if(!S_ISLNK(file->mLStat.st_mode))
            {
                return false;
            }
        }
    }
    
    return true;
}

VALUE cDirWnd::MarkFiles()
{


    VALUE result = rb_ary_new();

    if(Marking()) {
        for(int i=0; i<vector_size(mFiles); i++) {
            sFile* file = (sFile*)vector_item(mFiles, i);
            if(file->mMark) {
                rb_ary_push(result, rb_str_new2(file->mName));
            }
        }
    }
    else {
        if(ActiveDir() == this) {
            rb_ary_push(result, rb_str_new2(ActiveDir()->CursorFile()->mName));
        }
    }

    return result;

     
}

VALUE cDirWnd::MarkFilesConvert()
{


    VALUE result = rb_ary_new();

    if(Marking()) {
        for(int i=0; i<vector_size(mFiles); i++) {
            sFile* file = (sFile*)vector_item(mFiles, i);
            if(file->mMark) {
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                char buf[PATH_MAX];
                if(kanji_convert(file->mName, buf, PATH_MAX, gKanjiCodeFileName, gKanjiCode) == -1) {
                    rb_ary_push(result, rb_str_new2(file->mName));
                }
                else {
                    rb_ary_push(result, rb_str_new2(buf));
                }
#else
                rb_ary_push(result, rb_str_new2(file->mName));
#endif
            }
        }
    }
    else {
        if(ActiveDir() == this) {
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                char buf[PATH_MAX];
                if(kanji_convert(ActiveDir()->CursorFile()->mName, buf, PATH_MAX, gKanjiCodeFileName, gKanjiCode) == -1) {
                    rb_ary_push(result, rb_str_new2(ActiveDir()->CursorFile()->mName));
                }
                else {
                    rb_ary_push(result, rb_str_new2(buf));
                }
#else
                rb_ary_push(result, rb_str_new2(ActiveDir()->CursorFile()->mName));
#endif
        }
    }

    return result;

     
}



VALUE cDirWnd::MarkFilesFullPath()
{


    VALUE result = rb_ary_new();

    if(Marking()) {
        for(int i=0; i<vector_size(mFiles); i++) {
            sFile* file = (sFile*)vector_item(mFiles, i);
            if(file->mMark) {
                char tmp[PATH_MAX];
                sprintf(tmp, "%s%s", mPath, file->mName);
                rb_ary_push(result, rb_str_new2(tmp));
            }
        }
    }
    else {
        if(ActiveDir() == this) {
            char tmp[PATH_MAX];
            sprintf(tmp, "%s%s", mPath, ActiveDir()->CursorFile()->mName);
            rb_ary_push(result, rb_str_new2(tmp));
        }
    }

    return result;

     
}

VALUE cDirWnd::MarkFilesFullPathConvert()
{


    VALUE result = rb_ary_new();

    if(Marking()) {
        for(int i=0; i<vector_size(mFiles); i++) {
            sFile* file = (sFile*)vector_item(mFiles, i);
            if(file->mMark) {
                char tmp[PATH_MAX];
                sprintf(tmp, "%s%s", mPath, file->mName);

#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
                char buf[PATH_MAX];
                if(kanji_convert(tmp, buf, PATH_MAX, gKanjiCodeFileName, gKanjiCode) == -1) {
                    rb_ary_push(result, rb_str_new2(tmp));
                }
                else {
                    rb_ary_push(result, rb_str_new2(buf));
                }
#else
                rb_ary_push(result, rb_str_new2(tmp));
#endif
            }
        }
    }
    else {
        if(ActiveDir() == this) {
            char tmp[PATH_MAX];
            sprintf(tmp, "%s%s", mPath, ActiveDir()->CursorFile()->mName);
#if defined(HAVE_ICONV_H) || defined(HAVE_BICONV_H)
            char buf[PATH_MAX];
            if(kanji_convert(tmp, buf, PATH_MAX, gKanjiCodeFileName, gKanjiCode) == -1) {
                rb_ary_push(result, rb_str_new2(tmp));
            }
            else {
                rb_ary_push(result, rb_str_new2(buf));
            }
#else
            rb_ary_push(result, rb_str_new2(tmp));
#endif
        }
    }

    return result;

     
}

ALLOCATED string_obj* cDirWnd::MarkFilesSQuote()
{


    string_obj* result = string_new("");

    if(Marking()) {
        for(int i=0; i<vector_size(mFiles); i++) {
            sFile* file = (sFile*)vector_item(mFiles, i);

            /// is there a single quote char in file name? ///
            bool squote_name = false;
            const int len = strlen(file->mName);
            for(int i=0; i<len; i++) {
                if(file->mName[i] == '\'') {
                    squote_name = true;
                    break;
                }
            }

            if(squote_name) {
                if(file->mMark) {
                    string_push_back(result, "\"");
                    string_push_back(result, file->mName);
                    string_push_back(result, "\" ");
                }
            }
            else {
                if(file->mMark) {
                    string_push_back(result, "'");
                    string_push_back(result, file->mName);
                    string_push_back(result, "' ");
                }
            }
        }
    }
    else {
        if(ActiveDir() == this) {
            char* fname = ActiveDir()->CursorFile()->mName;
            bool squote_name = false;
            const int len = strlen(fname);
            for(int i=0; i<len; i++) {
                if(fname[i] == '\'') {
                    squote_name = true;
                    break;
                }
            }
            
            if(squote_name) {
                string_push_back(result, "\"");
                string_push_back(result, fname);
                string_push_back(result, "\"");
            }
            else {
                string_push_back(result, "'");
                string_push_back(result, fname);
                string_push_back(result, "'");
            }
        }
    }



    return result;
}

ALLOCATED string_obj* cDirWnd::MarkFilesSQuoteFullPath()
{


    string_obj* result = string_new("");

    if(Marking()) {
        for(int i=0; i<vector_size(mFiles); i++) {
            sFile* file = (sFile*)vector_item(mFiles, i);

            /// is there a single quote char in file name? ///
            bool squote_name = false;
            const int len = strlen(file->mName);
            for(int i=0; i<len; i++) {
                if(file->mName[i] == '\'') {
                    squote_name = true;
                    break;
                }
            }

            /// is there a single quote char in path name? ///
            const int len2 = strlen(mPath);
            for(int i=0; i<len2; i++) {
                if(mPath[i] == '\'') {
                    squote_name = true;
                    break;
                }
            }

            if(squote_name) {
                if(file->mMark) {
                    string_push_back(result, "\"");
                    string_push_back(result, mPath);
                    string_push_back(result, file->mName);
                    string_push_back(result, "\" ");
                }
            }
            else {
                if(file->mMark) {
                    string_push_back(result, "'");
                    string_push_back(result, mPath);
                    string_push_back(result, file->mName);
                    string_push_back(result, "' ");
                }
            }
        }
    }
    else {
        if(ActiveDir() == this) {
            bool squote_name = false;
            
            char* path = mPath;
            const int len = strlen(path);
            for(int i=0; i<len; i++) {
                if(path[i] == '\'') {
                    squote_name = true;
                    break;
                }
            }
            
            char* fname = ActiveDir()->CursorFile()->mName;
            const int len2 = strlen(fname);
            for(int i=0; i<len2; i++) {
                if(fname[i] == '\'') {
                    squote_name = true;
                    break;
                }
            }
            
            if(squote_name) {
                string_push_back(result, "\"");
                string_push_back(result, path);
                string_push_back(result, fname);
                string_push_back(result, "\"");
            }
            else {
                string_push_back(result, "'");
                string_push_back(result, path);
                string_push_back(result, fname);
                string_push_back(result, "'");
            }
        }
    }



    return result;
}

int cDirWnd::MarkFileNum()
{
    int result = 0;
    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);

        if(file->mMark) {
            result++;
        }
    }

    return result;
}

int cDirWnd::FileNum(char* fname)
{
    int* item = (int*)hash_item(mFileNum, fname);
    
    if(item == NULL) {
        return -1;
    }
    else {
        return *item;
    }
    
/*    
    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);

        if(strcmp(file->mName, fname) == 0) {
            return i;
        }
    }

    return -1;
    
*/    
}

double cDirWnd::MarkFileSize()
{
    double size = 0;
    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);

        if(file->mMark && !S_ISDIR(file->mStat.st_mode)) {
            size += file->mLStat.st_size;
        }
    }

    return size;
}

///////////////////////////////////////////////////////////////////////////////
// マーク中か？
///////////////////////////////////////////////////////////////////////////////
bool cDirWnd::Marking()
{
    for(int i=0; i<vector_size(mFiles); i++) {
        sFile* file = (sFile*)vector_item(mFiles, i);
        if(file->mMark) return true;
    }

    return false;
}
sFile* cDirWnd::CursorFile()
{
    return (sFile*)vector_item(mFiles, mCursor);
}

sFile* cDirWnd::File(int num)
{
    if(num>=0 && num<vector_size(mFiles)) {
        return (sFile*)vector_item(mFiles, num);
    }

    return NULL;
}
int cDirWnd::CursorX()
{
    const int maxx = mgetmaxx();
    const int maxy = mgetmaxy();

    const int dstack_exist = vector_size(gDirStack) > 0 ? 1 : 0;
    const int jobs_exist = vector_size(gJobs) > 0 ? 1 : 0;

    if(cDirWnd::gViewOption == kOneDir
        || cDirWnd::gViewOption == kOneDir2
        || cDirWnd::gViewOption == kOneDir3
        || cDirWnd::gViewOption == kOneDir5)
    {
        return mCursor/(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist);
    }
    else {
        return 0;
    }
}

int cDirWnd::CursorY()
{
    const int maxx = mgetmaxx();
    const int maxy = mgetmaxy();

    const int dstack_exist = vector_size(gDirStack) > 0 ? 1 : 0;
    const int jobs_exist = vector_size(gJobs) > 0 ? 1 : 0;

    if(cDirWnd::gViewOption == kOneDir 
       || cDirWnd::gViewOption == kOneDir2 
       || cDirWnd::gViewOption == kOneDir3
       || cDirWnd::gViewOption == kOneDir5)
    {
         return (mCursor-mScrollTop)
                     % (maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist);
    }
    else {
        return mCursor-mScrollTop;
    }
}

int cDirWnd::CursorMaxX()
{
    const int maxx = mgetmaxx();
    const int maxy = mgetmaxy();

    const int dstack_exist = vector_size(gDirStack) > 0 ? 1 : 0;
    const int jobs_exist = vector_size(gJobs) > 0 ? 1 : 0;

    if(cDirWnd::gViewOption == kOneDir 
        || cDirWnd::gViewOption == kOneDir2 
        || cDirWnd::gViewOption == kOneDir3
        || cDirWnd::gViewOption == kOneDir5)
    {
        return (vector_size(mFiles)-1)
                /(maxy-kMaxYMinus-dstack_exist-gViewHookLineNum-jobs_exist) + 1;
    }
    else {
        return 1;
    }
}

int cDirWnd::CursorMaxY()
{
    const int dstack_exist = vector_size(gDirStack) > 0 ? 1 : 0;
    const int jobs_exist = vector_size(gJobs) > 0 ? 1 : 0;
        
    return mgetmaxy() - kMaxYMinus -dstack_exist - gViewHookLineNum - jobs_exist;
}

int cDirWnd::Cursor()
{
    return mCursor;
}

int cDirWnd::CursorMax()
{
    return vector_size(mFiles);
}

void cDirWnd::MoveCursor(int index)
{


    mCursor = index;
    
    if(mCursor < 0) mCursor = 0;
    if(mCursor >= vector_size(mFiles)) mCursor = vector_size(mFiles)-1;

    rb_funcall(rb_cObject, rb_intern("cursor_move_hook"), 1, INT2FIX(index));


}

int cDirWnd::ScrollTop()
{
    return mScrollTop;
}

void cDirWnd::SetScrollTop(int index)
{
    mScrollTop = index;

    if(mScrollTop < 0) mScrollTop = 0;
    if(mScrollTop >= vector_size(mFiles)) mScrollTop = vector_size(mFiles)-1;
}

bool cDirWnd::IsLeftDir()
{
    return this == gLDir;
}

bool cDirWnd::IsRightDir()
{
    return this != gLDir;
}
