/*
 *   kioskdata.cpp
 *
 *   Copyright (C) 2003, 2004 Waldo Bastian <bastian@kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2 as
 *   published by the Free Software Foundation.
 *
 *   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 "kioskdata.h"

#include <qdom.h>
#include <qfile.h>

#include <kaction.h>
#include <kdebug.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kstdaction.h>

QDict<QString> *ComponentAction::s_stdActionCaptions = 0;

ComponentAction::ComponentAction()
{
}

ComponentAction::~ComponentAction()
{
}

static QDict<QString> *readStdActionCaptions()
{
  QDict<QString> *captions = new QDict<QString>;
  for(int i = KStdAction::ActionNone; true;)
  {
     i++;
     KAction *action = KStdAction::create((KStdAction::StdAction) i, 0, 0, 0, 0);
     if (!action)
       break;

     QString caption = action->text();
     caption.replace("&","");
       
     captions->insert(QString::fromLatin1(action->name()), new QString(caption));
  }
  return captions;
}

QString 
ComponentAction::expand(const QString &s)
{
  if (s.contains("%action"))
  {
     if (!s_stdActionCaptions)
       s_stdActionCaptions= readStdActionCaptions();
     
     QString action = key;
     action.replace("action/", "");
     QString *caption = s_stdActionCaptions->find(action);
     if (caption)
     {
        QString result = s;
        result.replace("%action", *caption);
        return result;
     }
  }
  return s;
}

bool
ComponentAction::load(const QDomElement &docElem)
{
  QString _type = docElem.attribute("type");
  if (_type == "immutable")
    type = ActImmutable;
  else if (_type == "action restriction")
    type = ActRestrict;
  else if (_type == "resource restriction")
    type = ActResource;
  else if (_type == "module")
    type = ActModule;
  else if (_type == "custom")
    type = ActCustom;
  else if (_type == "config")
    type = ActConfig;
  else 
  {  
#ifndef NDEBUG
    if (_type.isEmpty())
       kdFatal() << "'type' attribute missing or empty in action." << endl;
    else
       kdFatal() << "Unknown 'type' attribute '" << _type << "' in action." << endl;
#endif
    return false;
  }
   
  file = docElem.attribute("file");
  group = docElem.attribute("group");
  key = docElem.attribute("key");
  defaultValue = (docElem.attribute("default").lower() == "true");

  QDomNode n = docElem.firstChild();
  while( !n.isNull() ) 
  {
    QDomElement e = n.toElement(); // try to convert the node to an element.

    if (e.tagName() == "caption")
      caption = expand(i18n(e.text().simplifyWhiteSpace().utf8()));
    else if (e.tagName() == "description")
      description = expand(i18n(e.text().simplifyWhiteSpace().utf8()));
    else if (e.tagName() == "action")
    {
      ComponentAction *subAction = new ComponentAction;
      if (subAction->load(e))
      {
        subActions.append(subAction);
      }
      else
      {
        delete subAction;
      }
    }

    n = n.nextSibling();
  }

  return true;
}


ComponentData::ComponentData()
{
  actions.setAutoDelete(true);
}

ComponentData::~ComponentData()
{
}

bool ComponentData::loadActions(const QDomElement &docElem)
{
  QDomNode n = docElem.firstChild();
  while( !n.isNull() ) 
  {
    QDomElement e = n.toElement(); // try to convert the node to an element.

    if (e.tagName() != "action")
      return false;

    ComponentAction *action = new ComponentAction;
    if (action->load(e))
    {
      actions.append(action);
    }
    else
    {
      delete action;
    }
    n = n.nextSibling();
  }
  return true;
}

void
ComponentExecData::load(const QDomElement &e)
{
   exec = e.attribute("binary");
   dcop = e.attribute("dcop");
   options = QStringList::split(',', e.attribute("options"));
   args = QStringList::split(',', e.attribute("args"));
}

void
ComponentData::loadSetup(const QDomElement &docElem)
{
  QDomNode n = docElem.firstChild();
  while( !n.isNull() ) 
  {
    QDomElement e = n.toElement(); // try to convert the node to an element.

    if (e.tagName() == "mutable")
    {
      QString f = e.attribute("file");
      if (!f.isEmpty())
        mutableFiles.append(f);
    }
    else if (e.tagName() == "ignore")
    {
      QString f = e.attribute("file");
      if (!f.isEmpty())
        ignoreFiles.append(f);
    }

    n = n.nextSibling();
  }
}

bool ComponentData::load(const QDomElement &docElem)
{
  id = docElem.attribute("name");
  icon = docElem.attribute("icon");
  if (id.isEmpty())
    return false;
  QDomNode n = docElem.firstChild();
  while( !n.isNull() ) 
  {
    QDomElement e = n.toElement(); // try to convert the node to an element.

    if (e.tagName() == "caption")
    {
       caption = i18n(e.text().simplifyWhiteSpace().utf8());
    }
#if 0
    else if (e.tagName() == "description")
    {
       description = i18n(e.text().simplifyWhiteSpace().utf8());
    }
#endif
    else if (e.tagName() == "actions")
    {
       loadActions(e);
    }
    else if (e.tagName() == "setup")
    {
       setup.load(e);
       loadSetup(e);
    }
    else if (e.tagName() == "preview")
    {
       preview.load(e);
    }

    n = n.nextSibling();
  }
  return true;
}

KioskData::KioskData()
{
  m_componentData.setAutoDelete(true);
}

KioskData::~KioskData()
{
}

bool KioskData::load()
{
  QString filename = locate("appdata", "kiosk_data.xml");
  if (filename.isEmpty())
  {
    m_errorMsg = i18n("<qt>Could not find <b>kiosk_data.xml</b></qt>");
    return false;
  }

  QDomDocument doc;
  QFile file( filename );
  if ( !file.open( IO_ReadOnly ) )
  {
    m_errorMsg = i18n("<qt>Could not open <b>%1</b></qt>").arg(filename);
    return false;
  }

  QString errorMsg;
  int errorRow;
  int errorCol;
  if ( !doc.setContent( &file, &errorMsg, &errorRow, &errorCol ) ) 
  {
    m_errorMsg = i18n("<qt>Syntax error in <b>%1</b><br>Line %3, column %4: %2</qt>").arg(filename, errorMsg).arg(errorRow).arg(errorCol);
    file.close();
    return false;
  }
  file.close();
  
  QDomElement docElem = doc.documentElement();
  QDomNode n = docElem.firstChild();
  while( !n.isNull() ) 
  {
    QDomElement e = n.toElement(); // try to convert the node to an element.

    if (e.tagName() == "group")
    {
      ComponentData *componentData = new ComponentData;
      if (componentData->load(e))
      {
         m_componentData.insert(componentData->id, componentData);
         m_componentList.append(componentData->id);
      }
      else
      {
         delete componentData;
      }
    }

    n = n.nextSibling();
  }

  return true;
}
