
//  ------------------------------------------------------------------
//  GoldED+
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999-2000 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  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., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307 USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  Area scanning functions.
//  ------------------------------------------------------------------

#include <golded.h>
#include <gmoprot.h>


//  ------------------------------------------------------------------

extern bool in_arealist;
extern GPickArealist* PickArealist;

//  ------------------------------------------------------------------

void Area::UpdateAreadata()
{

    if(isscanned)
    {

        uint _unread = Msgn.Count() - lastread();
        if(not isvalidchg)
        {
            unread = _unread;
            isvalidchg = true;
        }
        isunreadchg = (unread != _unread);
        unread = _unread;
        word oldmask = AL.mask;
        AL.mask = 0;
        set_marked(make_bool(_unread));
        AL.mask = oldmask;
    }
}


//  ------------------------------------------------------------------

void Area::ScanArea()
{

    if(cmdlinedebughg)
        LOG.printf("- ScanArea: %s", echoid());

    area->Msgn = &Msgn;
    area->PMrk = &PMrk;

    area->scan_area();

    isscanned = true;

    UpdateAreadata();
}


//  ------------------------------------------------------------------

void Area::ScanAreaPM()
{

    if(cmdlinedebughg)
        LOG.printf("- ScanAreaPM: %s", echoid());

    area->Msgn = &Msgn;
    area->PMrk = &PMrk;

    area->scan_area_pm();

    isscanned = true;
    ispmscanned = true;

    UpdateAreadata();
}


//  ------------------------------------------------------------------

int AreaList::SetActiveAreaNo(int __areano)
{

    AA = idx[__areano];
    CurrArea = AA->areaid();
    CFG->originno = AA->originno();

    return CurrArea;  // Return the areaid
}


//  ------------------------------------------------------------------

int AreaList::AreaScan(int mode, uint currno, int pmscan, int& pmails, int& pmareas, const char* file)
{

    // Never scan if there's active area
    if(AA and AA->isopen())
        return false;

    gstrarray bag;
    int groupid = -1;

    // Load scan list into a string bag
    if (mode == SCAN_LIST)
    {
        Path tmp;
        strcpy(tmp, file ? file : ListScan.File());
        char* listfile;
        char* option=tmp;
        getkeyval(&listfile, &option);
        gfile fp(AddPath(CFG->goldpath, listfile), "rt");

        if (fp.isopen())
        {
            char buf[512];
            while (fp.Fgets(buf, sizeof(buf)))
            {
                strbtrim(buf);
                char* val = strtok(buf, ", \t");
                while(val)
                {
                    bag.push_back(val);
                    val = strtok(NULL, ", \t");
                }
            }
            fp.Fclose();
            if (((*option == '-') or (*option == '/')) and strieql(option+1, "delete"))
                remove(listfile);
        }
    }
    else if(mode == SCAN_GROUP)
    {
        groupid = idx[currno]->groupid();
    }

    int currid = AreaNoToId(currno);

    int scanned = false;

    // For optimized overlay usage, sort arealist by msgbase type, path, board and echoid
    if(*CFG->areascansort)
    {
        Sort(CFG->areascansort);
        scanned = true;
    }

    currno = AreaIdToNo(currid);

#ifndef GMB_NOPCB
    if(find(AL.basetypes, "PCBOARD"))    PcbWideOpen();
#endif
#ifndef GMB_NOGOLD
    if(find(AL.basetypes, "GOLDBASE"))   GoldWideOpen();
#endif
#ifndef GMB_NOHUDS
    if(find(AL.basetypes, "HUDSON"))     HudsWideOpen();
#endif

    for(uint n=0; n<idx.size(); n++)
    {

        // Check if ESC was pressed to skip the scan
        gkey xch = kbxhit();
        if(xch)
        {
            xch = kbxget();
            if(xch == Key_Esc)
                break;
            else
                kbput(xch);
        }

        SetActiveAreaNo(n);

        if(not AA->isseparator())
        {

            int scanit     = false;

            int dopmscan     = pmscan and AA->pmscan();
            int dopmscanexcl = pmscan and AA->pmscanexcl();
            int dopmscanincl = pmscan and AA->pmscanincl();

            int doscan     = AA->scan()     or dopmscan;
            //if Area is excluded from pm-scanning, scan it instead
            int doscanexcl = AA->scanexcl();
            int doscanincl = AA->scanincl() or dopmscanincl or (dopmscanexcl and doscan);

            if(mode != SCAN_STARTUP and pmscan)
                dopmscan = true;

            switch(mode)
            {
            case SCAN_STARTUP:
                if(doscan and (not doscanexcl or doscanincl))
                    scanit = true;
                break;
            case SCAN_ALL:
                if(not doscanexcl or doscanincl)
                    scanit = true;
                break;
            case SCAN_CURRENT:
                scanit = n == currno;
                break;
            case SCAN_MARKED:
                if(AA->ismarked())
                    scanit = true;
                break;
            case SCAN_MATCHING:
                if(striinc(area_maybe, AA->echoid()))
                    scanit = true;
                break;
            case SCAN_UNSCANNED:
                scanit = not (pmscan ? AA->ispmscanned : AA->isscanned);
                break;
            case SCAN_GROUP:
                scanit = AA->groupid() == groupid;
                break;
            case SCAN_NETMAIL:
                scanit = AA->isnet();
                break;
            case SCAN_LIST:
            {
                gstrarray::iterator i;
                for(i = bag.begin(); i != bag.end(); i++)
                    if(strwild(AA->echoid(), i->c_str()))
                    {
                        scanit = true;
                        break;
                    }
            }
            break;
            }

            if(scanit)
            {
                if(not AA->isopen())
                {
                    AA->Msgn.Reset();
                    AA->Mark.ResetAll();
                    AA->PMrk.ResetAll();
                }
                scanned = YES;
                if(not blanked)
                    update_statuslinef("%s %s", "", 1+LNG->ScanningArea, AA->echoid());
                if(dopmscan and (not dopmscanexcl or dopmscanincl))
                {
                    AA->ScanAreaPM();
                    uint count = AA->PMrk.Count();
                    if(count)
                    {
                        pmails += count;
                        pmareas++;
                    }
                    if(CFG->personalmail & PM_LISTONLY)
                        AA->PMrk.Reset();
                }
                else
                {
                    AA->ScanArea();
                }
            }
        }
    }

#ifndef GMB_NOHUDS
    if(find(AL.basetypes, "HUDSON"))     HudsWideClose();
#endif
#ifndef GMB_NOGOLD
    if(find(AL.basetypes, "GOLDBASE"))   GoldWideClose();
#endif
#ifndef GMB_NOPCB
    if(find(AL.basetypes, "PCBOARD"))    PcbWideClose();
#endif

    return scanned;
}


//  ------------------------------------------------------------------

void CheckSemaphores()
{

    Path file;
    int scanned = 0;
    int pmareas = 0;
    int pmails = 0;

    if(fexist(AddPath(CFG->areapath, CFG->semaphore.qwkimport)))
    {
        ImportQWK();
        remove(AddPath(CFG->areapath, CFG->semaphore.qwkimport));
        scanned++;
    }

    if(fexist(AddPath(CFG->areapath, CFG->semaphore.qwkexport)))
    {
        ExportQWK();
        remove(AddPath(CFG->areapath, CFG->semaphore.qwkexport));
    }

    if(fexist(AddPath(CFG->areapath, CFG->semaphore.soupimport)))
    {
        ImportSOUP();
        remove(AddPath(CFG->areapath, CFG->semaphore.soupimport));
        scanned++;
    }

    if(fexist(AddPath(CFG->areapath, CFG->semaphore.soupexport)))
    {
        ExportSOUP();
        remove(AddPath(CFG->areapath, CFG->semaphore.soupexport));
    }

    if(fexist(AddPath(CFG->areapath, CFG->semaphore.exitnow)) and in_arealist)
    {
        gkbd.quitall = YES;
        kbput(KK_AreaAbort);
        remove(AddPath(CFG->areapath, CFG->semaphore.exitnow));
    }
    else
    {

        if(fexist(AddPath(CFG->areapath, CFG->semaphore.scanall)))
        {
            scanned += AL.AreaScan(SCAN_ALL, 0, false, pmails, pmareas);
            remove(AddPath(CFG->areapath, CFG->semaphore.scanall));
        }

        if(fexist(AddPath(CFG->areapath, CFG->semaphore.scanthis)))
        {
            sprintf(file, "%s -delete", AddPath(CFG->areapath, CFG->semaphore.scanthis));
            scanned += AL.AreaScan(SCAN_LIST, 0, false, pmails, pmareas, file);
        }

        if(fexist(AddPath(CFG->areapath, CFG->semaphore.scannetmail)))
        {
            scanned += AL.AreaScan(SCAN_NETMAIL, 0, false, pmails, pmareas);
            remove(AddPath(CFG->areapath, CFG->semaphore.scannetmail));
        }

        if(fexist(AddPath(CFG->areapath, CFG->semaphore.pmscanall)))
        {
            scanned += AL.AreaScan(SCAN_ALL, 0, true, pmails, pmareas);
            remove(AddPath(CFG->areapath, CFG->semaphore.pmscanall));
        }

        if(fexist(AddPath(CFG->areapath, CFG->semaphore.pmscanthis)))
        {
            sprintf(file, "%s -delete", AddPath(CFG->areapath, CFG->semaphore.pmscanthis));
            scanned += AL.AreaScan(SCAN_LIST, 0, true, pmails, pmareas, file);
        }

        if(fexist(AddPath(CFG->areapath, CFG->semaphore.pmscannetmail)))
        {
            scanned += AL.AreaScan(SCAN_NETMAIL, 0, true, pmails, pmareas);
            remove(AddPath(CFG->areapath, CFG->semaphore.pmscannetmail));
        }
    }

    if(scanned)
    {
        AL.Sort();
        if(in_arealist and not blanked)
        {
            PickArealist->update();        // update arealist-display
            PickArealist->do_delayed();    // update statusline
        }
        AL.WriteGoldLast();
    }
}


//  ------------------------------------------------------------------

