// -*- c-basic-offset: 4 -*-

/** @file CPDetectorConfig.cpp
 *
 *  @brief implementation of CPDetectorSetting and CPDetectorConfig classes, 
 *         which are for storing and changing settings of different CP detectors
 *
 *  @author Thomas Modes
 *
 */

/*  This 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 software 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public
 *  License along with this software. If not, see
 *  <http://www.gnu.org/licenses/>.
 *
 */

#ifdef _WIN32
#include "wx/msw/wrapwin.h"
// Mingw define still DIFFERENCE, which conflicts with vigra, so disable it
#undef DIFFERENCE
#endif
#include "icpfind/CPDetectorConfig.h"
#include "hugin_config.h"
#include <wx/fileconf.h>

/** description of default cp generator, for fall back procedure */
wxString default_cpgenerator_desc("Hugin's Cpfind");
/** program name of default cp generator, for fall back procedure */
#ifdef _WIN32
wxString default_cpgenerator_prog("cpfind.exe");
#else
wxString default_cpgenerator_prog("cpfind");
#endif
/** arguments for default cp generator, for fall back procedure */
wxString default_cpgenerator_args("-o %o %s");

void CPDetectorConfig::Read(wxConfigBase *config,wxString loadFromFile)
{
    settings.Clear();
    int count=config->Read("/AutoPano/AutoPanoCount",0l);
    default_generator=config->Read("/AutoPano/Default",0l);
    if(count>0)
    {
        for(int i=0;i<count;i++)
            ReadIndex(config, i);
    };
    if(settings.GetCount()==0)
    {
        if(loadFromFile.IsEmpty())
        {
            ResetToDefault();
        }
        else
        {
            ReadFromFile(loadFromFile);
        };
    };
    if(default_generator>=settings.GetCount())
        default_generator=0;
};

void CPDetectorConfig::ReadFromFile(wxString filename)
{
    if(wxFile::Exists(filename))
    {
        wxFileConfig fconfig("hugin",wxEmptyString,filename);
        Read(&fconfig);
    }
    else
    {
        ResetToDefault();
    };
};

void CPDetectorConfig::ReadIndex(wxConfigBase *config, int i)
{
    wxString path=wxString::Format("/AutoPano/AutoPano_%d",i);
    if(config->HasGroup(path))
    {
        CPDetectorSetting* gen=new CPDetectorSetting;
        if(gen->Read(config,path))
        {
            settings.Add(gen);
            if(i==default_generator)
            {
                default_generator=settings.Index(*gen,true);
            };
        };
    };
};

void CPDetectorConfig::Write(wxConfigBase *config)
{
    int count=settings.Count();
    config->Write("/AutoPano/AutoPanoCount",count);
    config->Write("/AutoPano/Default",(int)default_generator);
    if(count>0)
    {
        for(int i=0;i<count;i++)
            WriteIndex(config, i);
    };
};

void CPDetectorConfig::WriteToFile(wxString filename)
{
    wxFileConfig fconfig("hugin",wxEmptyString,filename);
    Write(&fconfig);
    fconfig.Flush();
};

void CPDetectorConfig::WriteIndex(wxConfigBase *config, int i)
{
    wxString path=wxString::Format("/AutoPano/AutoPano_%d",i);
    settings[i].Write(config,path);
};

void CPDetectorConfig::ResetToDefault()
{
    settings.Clear();
    settings.Add(new CPDetectorSetting());
    default_generator=0;
};

void CPDetectorConfig::FillControl(wxControlWithItems *control,bool select_default,bool show_default)
{
    control->Clear();
    for(unsigned int i=0;i<settings.GetCount();i++)
    {
        wxString s=settings[i].GetCPDetectorDesc();
        if(show_default && i==default_generator)
            s=s+" ("+_("Default")+")";
        control->Append(s);
    };
    if(select_default)
        control->SetSelection(default_generator);
};

void CPDetectorConfig::Swap(int index)
{
    CPDetectorSetting* setting=settings.Detach(index);
    settings.Insert(setting,index+1);
    if(default_generator==index)
        default_generator=index+1;
    else 
        if(default_generator==index+1)
            default_generator=index;
};

void CPDetectorConfig::SetDefaultGenerator(unsigned int new_default_generator)
{
    if(new_default_generator<GetCount())
        default_generator=new_default_generator;
    else
        default_generator=0;
};

#include <wx/arrimpl.cpp> 
WX_DEFINE_OBJARRAY(ArraySettings);

CPDetectorSetting::CPDetectorSetting()
{
    type=CPDetector_AutoPanoSift;
    desc=default_cpgenerator_desc;
    prog=default_cpgenerator_prog;
    args=default_cpgenerator_args;
    args_cleanup=wxEmptyString;
    prog_matcher=wxEmptyString;
    args_matcher=wxEmptyString;
    prog_stack=wxEmptyString;
    args_stack=wxEmptyString;
    option=true;
    CheckValues();
};

void CPDetectorSetting::CheckValues()
{
    if(type==CPDetector_AutoPano)
    {
        if(!prog_matcher.IsEmpty())
        {
            prog_matcher=wxEmptyString;
            args_matcher=wxEmptyString;
        };
    };
};

const bool CPDetectorSetting::IsCleanupPossible(CPDetectorType _type)
{
    return (_type==CPDetector_AutoPanoSiftMultiRow || 
            _type==CPDetector_AutoPanoSiftMultiRowStack ||
            _type==CPDetector_AutoPanoSiftPreAlign);
};

const bool CPDetectorSetting::ContainsStacks(CPDetectorType _type)
{
    return (_type==CPDetector_AutoPanoSiftStack || _type==CPDetector_AutoPanoSiftMultiRowStack);
};

bool CPDetectorSetting::Read(wxConfigBase *config, wxString path)
{
    if(!config->Exists(path))
    {
        return false;
    }
    type=(CPDetectorType)config->Read(path+"/Type",CPDetector_AutoPanoSift);
    desc=config->Read(path+"/Description",default_cpgenerator_desc);
    prog=config->Read(path+"/Program",default_cpgenerator_prog);
    args=config->Read(path+"/Arguments",default_cpgenerator_args);
    if(IsCleanupPossible())
    {
        args_cleanup=config->Read(path+"/ArgumentsCleanup",wxEmptyString);
    }
    else
    {
        args_cleanup=wxEmptyString;
    };
    prog_matcher=config->Read(path+"/ProgramMatcher",wxEmptyString);
    args_matcher=config->Read(path+"/ArgumentsMatcher",wxEmptyString);
    if(ContainsStacks())
    {
        prog_stack=config->Read(path+"/ProgramStack",wxEmptyString);
        args_stack=config->Read(path+"/ArgumentsStack",wxEmptyString);
    }
    else
    {
        prog_stack=wxEmptyString;
        args_stack=wxEmptyString;
    };
    config->Read(path+"/Option",&option,true);
    CheckValues();
    return true;
};

void CPDetectorSetting::Write(wxConfigBase *config, wxString path)
{
    config->Write(path+"/Type",int(type));
    config->Write(path+"/Description",desc);
    config->Write(path+"/Program",prog);
    config->Write(path+"/Arguments",args);
    config->Write(path+"/ProgramMatcher",prog_matcher);
    config->Write(path+"/ArgumentsMatcher",args_matcher);
    if(IsCleanupPossible())
    {
        config->Write(path+"/ArgumentsCleanup",args_cleanup);
    };
    if(ContainsStacks())
    {
        config->Write(path+"/ProgramStack",prog_stack);
        config->Write(path+"/ArgumentsStack",args_stack);
    };
    config->Write(path+"/Option",option);
};


