/*****************************************************************************
 *   Copyright (C) 2003 by Fred Schaettgen <kdebluetooth@schaettgen.de>
 *   Copyright (C) 2004-2005 by Alex Ibrado <alex@kdex.org>
 *
 *   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.
 *****************************************************************************/
#include <kapplication.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kprocio.h>
#include <qfile.h>
#include <qfileinfo.h>
#include "scriptscontroller.h"


ScriptsController::ScriptsController(QObject* parent) :
    Controller(parent)
{
    scriptsCfg = KGlobal::config();
    scriptsCfg->setGroup("scripts");
    scriptsList = scriptsCfg->readListEntry("scriptsList");
    selectedScript = 0;
    lastRepeat = lastShuffle = false;
    useCustomPlaylist = showingCustomPlaylist = false;
    mustListScripts = true;

    controllerInfo.name = "scripts";
    controllerInfo.pathToApp = "";
}

void ScriptsController::commandCHCK() {
    // Checks that the server is running OK
}

void ScriptsController::commandDINF(unsigned int &bitrate,
    unsigned int &sampleRate, unsigned int &channels)
{
    // Gets detailed information about the current song

    bool useFake = true;

    if(showingCustomPlaylist) {
        QStringList output;
        call(scriptsList[selectedScript], QStringList("DINF"), &output);
        if(output.count()==3) {
            bitrate = output[0].toInt();
            sampleRate = output[1].toInt();
            channels = output[2].toInt();
            useFake = false;
        }
    }

    if(useFake) {
        bitrate = 128;
        sampleRate = 44;
        channels = 2;
    }
}

void ScriptsController::commandFADE() {
    // Stops the current song by fading it out
    call(scriptsList[selectedScript], QStringList("FADE"));
}

void ScriptsController::commandFFWD() {
    // Fast-forwards by five seconds
    call(scriptsList[selectedScript], QStringList("FFWD"));
}

int ScriptsController::commandFINF(QString /*filename*/) {
    // Gets information about the specified file
    return 0;
}

Controller::SongInfo ScriptsController::parseInfo(QStringList output) {
    // Gets information from script
    Controller::SongInfo info;
    bool useFake = true;

    // Some scripts may have feedback, but no custom playlist
    if(output.count()==6) {
        info.length = output[0].toInt();
        info.currentTime = output[1].toInt();
        info.playState = output[2].toInt();
        info.repeat = output[3].toInt()==0?false:true;
        info.shuffle = output[4].toInt()==0?false:true;
        info.trackName = output[5];
        useFake = false;
    }

    if(useFake) {
        info.length = 0;
        info.currentTime = 0;
        info.playState = mustListScripts?0:1; 
        info.repeat = lastRepeat; // make it go on/off
        info.shuffle = lastShuffle;
        QFileInfo fi(scriptsList[selectedScript]);
        info.trackName = fi.baseName(true); // keep any extensions eg .sh
    }
    return info;
}


Controller::SongInfo ScriptsController::commandINFO() {
    QStringList output;
    call(scriptsList[selectedScript], QStringList("INFO"), &output);
    return parseInfo(output);
}

Controller::SongInfo ScriptsController::commandINF2() {
    QStringList output;
    call(scriptsList[selectedScript], QStringList("INF2"), &output);
    return parseInfo(output);
}

void ScriptsController::commandLADD(QString filename) {
    // Adds the specified file to the playlist
    if(showingCustomPlaylist) {
        call(scriptsList[selectedScript], QStringList("LADD") << filename);
    } else {
        scriptsCfg->setGroup("scripts");
        scriptsList = scriptsCfg->readListEntry("scriptsList");
        scriptsList.append(filename);
        scriptsCfg->writeEntry("scriptsList",scriptsList);
    }
}

void ScriptsController::commandNEXT() {
    // Plays the next song in the playlist
    call(scriptsList[selectedScript], QStringList("NEXT"));
}

void ScriptsController::commandPAUS() {
    // Pauses the current song
    call(scriptsList[selectedScript], QStringList("PAUS"));
}

void ScriptsController::commandPLAY(QString filename, bool clear) {
    // Plays the specified file
    if(clear)
        commandRMAL();

    if(showingCustomPlaylist) {
        // User would expect to play it
        call(scriptsList[selectedScript], QStringList("PLAY") << filename);
    } else {
        // If not a script, would be nice to pass it to the appropriate player
        call(filename, QStringList("PLAY"));
    }
}

QStringList ScriptsController::commandPLST(int &curPos, bool /*useFilenames*/) {
    // Writes the current playlist to the phone
    // TODO: Use savePlaylist()

    QStringList playlist;
    bool showScriptList = false;
    if(mustListScripts) {
        // First run
        showScriptList = true;
        // mustListScripts set to false upon SLCT
    } else if(showingCustomPlaylist && !useCustomPlaylist) {
        // User wants to revert to script listing
        showScriptList = true;
        useCustomPlaylist = true; // for next time
    } else {
        // See if the script has a custom playlist
        QStringList output;
        call(scriptsList[selectedScript], QStringList("PLST"), &output);
        if(output.count()>0) {
            // Custom playlist should return curPos as first line

            showingCustomPlaylist = true;
            playlist.append("[up]");

            unsigned int customEntries=0;
            for(unsigned int n=1; n<output.count(); ++n) {
                playlist.append(output[n]);
                customEntries++;
            }
            curPos = output[0].toInt();
            if(customEntries>0) curPos++; 

        } else {
            // No custom list
            showScriptList = true;
        }
    }

    if(showScriptList) {
        scriptsCfg->setGroup("scripts");
        QStringList scriptsList = scriptsCfg->readListEntry("scriptsList");
        for(unsigned int n=0; n<scriptsList.count(); ++n) {
            QFileInfo fi(scriptsList[n]);
            playlist.append(fi.baseName());
        }
        curPos=selectedScript;
        showingCustomPlaylist = false;
        useCustomPlaylist = true; // for next time
    }
    return playlist;
}

void ScriptsController::commandPREV() {
    // Plays the previous song in the playlist
    call(scriptsList[selectedScript], QStringList("PREV"));
}

void ScriptsController::commandREPT(bool repeat) {
    // Enables or disables repeat mode
    lastRepeat = repeat;
    call(scriptsList[selectedScript], QStringList("REPT") << (repeat?"1":"0"));
}

void ScriptsController::commandRMAL() {
    // Removes all songs from the playlist
    if(showingCustomPlaylist) {
        call(scriptsList[selectedScript], QStringList("RMAL"));
    } else {
        scriptsList.clear();
        scriptsCfg->setGroup("scripts");
        scriptsCfg->deleteEntry("scriptsList");
        mustListScripts = true;
    }
}

void ScriptsController::commandRWND() {
    // Rewinds by five seconds
    call(scriptsList[selectedScript], QStringList("RWND"));
}

void ScriptsController::commandSHFL(bool shuffle) {
    // Enables or disables shuffle mode
    lastShuffle = shuffle;
    call(scriptsList[selectedScript], QStringList("SHFL") << (shuffle?"1":"0"));
}

void ScriptsController::commandSHUT() {
    // Shuts down the PC
    call("shutdown", QStringList("-h") << "now");
}

void ScriptsController::commandSLCT(Q_UINT16 index) {
    // Selects song at [index] in playlist
    if(showingCustomPlaylist) {
        if(index == 0) {
            // Revert to script listing
            // Don't change selectedScript so that a refresh 
            //  will show the correct script still selected
            useCustomPlaylist = false;
        } else {
            call(scriptsList[selectedScript], QStringList("SLCT") << QString("%1").arg(index-1));
        }
    } else {
        mustListScripts = false;
        selectedScript = index;
    }
}

void ScriptsController::commandSTEN() {
    // Stops playing at the end of the current song
    call(scriptsList[selectedScript], QStringList("STEN"));
}

void ScriptsController::commandSTOP() {
    // Stops the current song immediately
    call(scriptsList[selectedScript], QStringList("STOP"));
}

void ScriptsController::commandSTRT() {
    // Starts playing the current song
    call(scriptsList[selectedScript], QStringList("STRT"));
}

void ScriptsController::commandVOLM(Q_UINT8 volume) {
    // Sets the volume to the value specified
    call(scriptsList[selectedScript], QStringList("VOLM") << QString("%1").arg(volume));
}

bool ScriptsController::commandFULL() {
    // Toggle fullscreen mode
    call(scriptsList[selectedScript], QStringList("FULL"));
    return true;
}

void ScriptsController::commandSEEK(Q_UINT32 seconds) {
    // Jump to specified position
    call(scriptsList[selectedScript], QStringList("SEEK") << QString("%1").arg(seconds));
}

Q_UINT32 ScriptsController::commandPLEN() {
    // Return playlist length
    Q_UINT32 plen=0;
    QStringList output;
    call(scriptsList[selectedScript], QStringList("PLEN"), &output);
    if(output.count()>0) {
        plen = output[0].toInt();
    }
    return plen;
}

bool ScriptsController::commandGVOL(Q_UINT8 &volume) {
    // Get current volume
    QStringList output;
    call(scriptsList[selectedScript], QStringList("GVOL"), &output);
    if(output.count()>0) {
        volume = output[0].toInt();
        return true;
    } else {
        return false;
    }
}

// Fred's call routine
bool ScriptsController::call(QString exe, QStringList params, QStringList* output)
{
    if (output) {
        *output = QStringList();
    }
    KProcIO procio;
    procio << exe;
    for (unsigned int n=0; n<params.count(); ++n) {
        procio << params[n];
    }
    if (procio.start(KProcess::Block)) {
        QString line;
        if (output) {
            while (procio.readln(line) >=0) {
                output->append(line);
            }
        }
        return true;
    }
    else {
        return false;
    }
} 

int ScriptsController::currentIndex() {
    return -1;
}

ScriptsController::~ScriptsController()
{
}


#include "scriptscontroller.moc"
