/*
 *  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
 */

#include <stdlib.h>

#include <qrect.h>
#include <qwidget.h>

#include "ConfigC.h"
#include "ConfigFile.h"

ConfigFile::ConfigFile(const char* inFileName)
: fileName(inFileName)
{
}

const QString& ConfigFile::getFileName() const
{
    return fileName;
}

void ConfigFile::restoreGeom(QWidget* widget)
{
    int x,y,w,h;
    getValue(ConfigC::keys[ConfigC::X],x);
    getValue(ConfigC::keys[ConfigC::Y],y);
    getValue(ConfigC::keys[ConfigC::W],w);
    getValue(ConfigC::keys[ConfigC::H],h);
    QRect g(x,y,w,h);
    QRect z(0,0,0,0);
    if ( g!=z )
    {
        // See 'Window Geometry' docs from Qt.
        widget->resize(w,h);
        widget->move(x,y);
    }
}

void ConfigFile::saveGeom(const QWidget* widget)
{
    setEntry( ConfigC::keys[ConfigC::X], widget->x() );
    setEntry( ConfigC::keys[ConfigC::Y], widget->y() );
    setEntry( ConfigC::keys[ConfigC::W], widget->width() );
    setEntry( ConfigC::keys[ConfigC::H], widget->height() );
}

const AudioConfig& ConfigFile::getAudioConfig() const
{
    return myAudioConfig;
}

const emuConfig& ConfigFile::getEmuConfig() const
{
    return myEmuConfig;
}

const HVSC_Config& ConfigFile::getHVSC_Config() const
{
    return myHVSC_Config;
}

const MixerConfig& ConfigFile::getMixerConfig() const
{
    return myMixerConfig;
}

void ConfigFile::setAudioConfig(const AudioConfig& inAudioConfig)
{
    myAudioConfig = inAudioConfig;
    // Audio
    setGroup(ConfigC::groups[ConfigC::Audio]);
    setEntry(ConfigC::keys[ConfigC::Frequency],myAudioConfig.frequency);
    setEntry(ConfigC::keys[ConfigC::Channels],myAudioConfig.channels);
    setEntry(ConfigC::keys[ConfigC::BitsPerSample],myAudioConfig.precision);
    setEntry(ConfigC::keys[ConfigC::SampleEncoding],myAudioConfig.encoding);
    setEntry(ConfigC::keys[ConfigC::BufSize],myAudioConfig.bufSize);
    setEntry(ConfigC::keys[ConfigC::MaxFrags],myAudioConfig.maxFrags);
    setEntry(ConfigC::keys[ConfigC::FragSize],myAudioConfig.fragSize);
}

void ConfigFile::setEmuConfig(const emuConfig& inEmuConfig)
{
    myEmuConfig = inEmuConfig;
    // Emulation
    setGroup(ConfigC::groups[ConfigC::Emulation]);
    setEntry(ConfigC::keys[ConfigC::ClockSpeed],myEmuConfig.clockSpeed);
    setEntry(ConfigC::keys[ConfigC::ForceSongSpeed],myEmuConfig.forceSongSpeed);
    setEntry(ConfigC::keys[ConfigC::MemoryMode],myEmuConfig.memoryMode);
    setEntry(ConfigC::keys[ConfigC::MOS8580],myEmuConfig.mos8580);
    setEntry(ConfigC::keys[ConfigC::MeasuredMasterVolume],myEmuConfig.measuredVolume);
    setEntry(ConfigC::keys[ConfigC::UseFilter],myEmuConfig.emulateFilter);
    setEntry(ConfigC::keys[ConfigC::FilterFs],myEmuConfig.filterFs);;
    setEntry(ConfigC::keys[ConfigC::FilterFm],myEmuConfig.filterFm);;
    setEntry(ConfigC::keys[ConfigC::FilterFt],myEmuConfig.filterFt);
}

void ConfigFile::setHVSC_Config(const HVSC_Config& inHVSC_Config)
{
    myHVSC_Config = inHVSC_Config;
    // HVSC, STIL
    setGroup(ConfigC::groups[ConfigC::HVSC_STIL]);
    setEntry(ConfigC::keys[ConfigC::HVSC_Root],myHVSC_Config.hvscRootPath.path());
    setEntry(ConfigC::keys[ConfigC::HVSC_BugEntries],myHVSC_Config.showBugListEntries);
    setEntry(ConfigC::keys[ConfigC::STIL_ShowGlobal],myHVSC_Config.showGlobalComments);
    setEntry(ConfigC::keys[ConfigC::STIL_ShowEntries],myHVSC_Config.showStilEntries);
    setEntry(ConfigC::keys[ConfigC::STIL_AllOrSong],myHVSC_Config.showForFile);
    setEntry(ConfigC::keys[ConfigC::STIL_AutoResize],myHVSC_Config.autoResize);
    setEntry(ConfigC::keys[ConfigC::STIL_MaxHeight],myHVSC_Config.maxHeight.toInt());
}

void ConfigFile::setMixerConfig(const MixerConfig& inMixerConfig)
{
    myMixerConfig = inMixerConfig;
    // Mixer
    setGroup(ConfigC::groups[ConfigC::Mixer]);
    removeEntry(ConfigC::keys[ConfigC::BitsPerSample]);  // (ms) bug from 1.5.0
    setEntry(ConfigC::keys[ConfigC::MixerType],myEmuConfig.volumeControl);
    setEntry(ConfigC::keys[ConfigC::AutoPanning],myEmuConfig.autoPanning);
    setEntry(ConfigC::keys[ConfigC::Voice1Vol],(int)myMixerConfig.volTotal[0]);
    setEntry(ConfigC::keys[ConfigC::Voice2Vol],(int)myMixerConfig.volTotal[1]);
    setEntry(ConfigC::keys[ConfigC::Voice3Vol],(int)myMixerConfig.volTotal[2]);
    setEntry(ConfigC::keys[ConfigC::Voice4Vol],(int)myMixerConfig.volTotal[3]);
    setEntry(ConfigC::keys[ConfigC::PanPosLeftHQ],myMixerConfig.mergePanPosLeft(myMixerConfig.volHQ));
    setEntry(ConfigC::keys[ConfigC::PanPosRightHQ],myMixerConfig.mergePanPosRight(myMixerConfig.volHQ));
    setEntry(ConfigC::keys[ConfigC::PanPosLeftFP],myMixerConfig.mergePanPosLeft(myMixerConfig.volFP));
    setEntry(ConfigC::keys[ConfigC::PanPosRightFP],myMixerConfig.mergePanPosRight(myMixerConfig.volFP));
}

// -------------------------------------------------------------------- Input

bool ConfigFile::load()
{
    bool success = IniFile::load(fileName);

    // Audio
    
    setGroup(ConfigC::groups[ConfigC::Audio]);
    getValue(ConfigC::keys[ConfigC::Frequency],myAudioConfig.frequency);
    getValue(ConfigC::keys[ConfigC::Channels],myAudioConfig.channels);
    getValue(ConfigC::keys[ConfigC::BitsPerSample],myAudioConfig.precision);
    getValue(ConfigC::keys[ConfigC::SampleEncoding],myAudioConfig.encoding);
    getValue(ConfigC::keys[ConfigC::BufSize],myAudioConfig.bufSize);
    getValue(ConfigC::keys[ConfigC::MaxFrags],myAudioConfig.maxFrags);
    getValue(ConfigC::keys[ConfigC::FragSize],myAudioConfig.fragSize);

    // Emulator

    setGroup(ConfigC::groups[ConfigC::Emulation]);
    getValue(ConfigC::keys[ConfigC::ClockSpeed],myEmuConfig.clockSpeed);
    getValue(ConfigC::keys[ConfigC::ForceSongSpeed],myEmuConfig.forceSongSpeed);
    getValue(ConfigC::keys[ConfigC::MemoryMode],myEmuConfig.memoryMode);
    getValue(ConfigC::keys[ConfigC::MOS8580],myEmuConfig.mos8580);
    getValue(ConfigC::keys[ConfigC::MeasuredMasterVolume],myEmuConfig.measuredVolume);
        
    getValue(ConfigC::keys[ConfigC::UseFilter],myEmuConfig.emulateFilter);
    getValue(ConfigC::keys[ConfigC::FilterFs],myEmuConfig.filterFs);
    getValue(ConfigC::keys[ConfigC::FilterFm],myEmuConfig.filterFm);
    getValue(ConfigC::keys[ConfigC::FilterFt],myEmuConfig.filterFt);
        
    // HVSC/STIL
             
    setGroup(ConfigC::groups[ConfigC::HVSC_STIL]);
    myHVSC_Config.hvscRootPath.setPath( getString(ConfigC::keys[ConfigC::HVSC_Root]) );

    getValue(ConfigC::keys[ConfigC::STIL_ShowGlobal],myHVSC_Config.showGlobalComments);
    getValue(ConfigC::keys[ConfigC::STIL_ShowEntries],myHVSC_Config.showStilEntries);
    getValue(ConfigC::keys[ConfigC::HVSC_BugEntries],myHVSC_Config.showBugListEntries);
    getValue(ConfigC::keys[ConfigC::STIL_AllOrSong],myHVSC_Config.showForFile);
    myHVSC_Config.showForCurrentSong = !myHVSC_Config.showForFile;
    getValue(ConfigC::keys[ConfigC::STIL_AutoResize],myHVSC_Config.autoResize);
    getValue(ConfigC::keys[ConfigC::STIL_MaxHeight],myHVSC_Config.maxHeight);
        
    // Mixer
    
    setGroup(ConfigC::groups[ConfigC::Mixer]);
    getValue(ConfigC::keys[ConfigC::MixerType],myEmuConfig.volumeControl);
    getValue(ConfigC::keys[ConfigC::AutoPanning],myEmuConfig.autoPanning);
    getValue(ConfigC::keys[ConfigC::Voice1Vol],myMixerConfig.volTotal[0]);
    getValue(ConfigC::keys[ConfigC::Voice2Vol],myMixerConfig.volTotal[1]);
    getValue(ConfigC::keys[ConfigC::Voice3Vol],myMixerConfig.volTotal[2]);
    getValue(ConfigC::keys[ConfigC::Voice4Vol],myMixerConfig.volTotal[3]);
    int mergedVol;
    getValue(ConfigC::keys[ConfigC::PanPosLeftHQ],mergedVol);
    myMixerConfig.readMergedPanPosLeft(myMixerConfig.volHQ,mergedVol);
    getValue(ConfigC::keys[ConfigC::PanPosRightHQ],mergedVol);
    myMixerConfig.readMergedPanPosRight(myMixerConfig.volHQ,mergedVol);
    getValue(ConfigC::keys[ConfigC::PanPosLeftFP],mergedVol);
    myMixerConfig.readMergedPanPosLeft(myMixerConfig.volFP,mergedVol);
    getValue(ConfigC::keys[ConfigC::PanPosRightFP],mergedVol);
    myMixerConfig.readMergedPanPosRight(myMixerConfig.volFP,mergedVol);
    
    (myAudioConfig.channels == 1) ? (myEmuConfig.channels = SIDEMU_MONO)
        : (myEmuConfig.channels = SIDEMU_STEREO);
    (myAudioConfig.precision == 8) ? (myEmuConfig.bitsPerSample = SIDEMU_8BIT)
        : (myEmuConfig.bitsPerSample = SIDEMU_16BIT);
    (myAudioConfig.encoding == 0x7f) ? (myEmuConfig.sampleFormat = SIDEMU_SIGNED_PCM)
        : (myEmuConfig.sampleFormat = SIDEMU_UNSIGNED_PCM);

    return success;
}

// ------------------------------------------------------------------- Output

bool ConfigFile::save()
{
    return IniFile::save(fileName);
}

