/*------------------------------------------------------------------------------
 src/lib/djWidget/app.cxx

 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

//#define DJ_DBG
#include "djApp.h"
#include <djDialog.h>
#include <djImageOpCoreWidget.h>
#include <djImageOpGenWidget.h>
#include <djImageOpColorWidget.h>
#include <djImageOpXformWidget.h>
#include <djImageOpCompWidget.h>
#include <djImageIoTgaWidget.h>
#include <djImageIoSgiWidget.h>
#include <djImageIoPpmWidget.h>
#include <djImageIoDpxWidget.h>
#include <FL/Fl.H>
#include <FL/Fl_Tooltip.H>
#include <FL/Fl_Preferences.H>

namespace dj {

App::App(const Str & name, int & argc, char ** argv) :
  dj::ImageApp(name, argc, argv),
  _valid(false),
  _font(Fl_Font(0)), _fontBold(Fl_Font(0)), _fontSize(0),
  _layoutSpacing(6), _layoutMargin(6), _layoutWidgetMargin(4),
    _layoutButtonSize(50), _layoutThumbnailSize(64),
  _messageDialog(0), _questionDialog(0), _inputDialog(0), _fileBrowser(0),
  _tooltips(true),
  _prefs(name), _prefsInit(false)
{
  DJ_DBG_FNC("dj::App::App");
  
  Fl::visual(FL_DOUBLE | FL_RGB);

  // Plugin factories.
  //
  _imageOpWidgetFactory.set(searchPathList());
  _imageLoadWidgetFactory.set(searchPathList());
  _imageSaveWidgetFactory.set(searchPathList());
  imageFactoryInit();
  
  // XXX
  //
# ifdef DJ_IRIX
  colorFg(1.0);
  colorBg(0.5);
  colorBg2(0.4);
# else
  colorFg(1.0);
  colorBg(0.6);
  colorBg2(0.5);
# endif
  font(FL_HELVETICA);
  fontBold(FL_HELVETICA_BOLD);
  fontSize(12);
  
  // Dialogs.
  //
  _messageDialog = new MessageDialog;
  _questionDialog = new QuestionDialog;
  _inputDialog = new InputDialog;
  _fileBrowser = new FileBrowserDialog;

  // Preferences.
  //
  prefsGet();
  
  // Initialize.
  //
  tooltipsUpdate();
}

App::~App()
{
  DJ_DBG_FNC("dj::App::~App");

  if (_valid) prefsSet();
  
  delete _fileBrowser;
  delete _inputDialog;
  delete _questionDialog;
  delete _messageDialog;
}

int App::exec()
{
  DJ_DBG_FNC("dj::App::exec");
  
  if (_valid && exitValue() == 0) Fl::run();
  return exitValue();
}

void App::exit()
{
  DJ_DBG_FNC("dj::App::exit");
  
  for (ListIt<Fl_Window *> it = _windowList; it.isValid(); ++it)
    it()->hide();
}

void App::valid(bool in)
{
  DJ_DBG_FNC("dj::App::valid");
  DJ_DBG_PRN("in = " << in);
  
  _valid = true;
}

void App::error(const Str & in) const
{
  if (_valid) {
    _messageDialog->set(in);
    _messageDialog->show();
  } else
    ImageApp::error(in);
}

void App::print(const Str & in) const
{
  if (_valid) {
    _messageDialog->set(in);
    _messageDialog->show();
  } else
    ImageApp::print(in);
}

void App::colorFg(const Color & in)
{
  _colorFg = in;
  Color tmp(PIXEL_RGB, PIXEL_U8);
  convert(_colorFg, &tmp);
  Fl::foreground(tmp.u8(0), tmp.u8(1), tmp.u8(2));
}

void App::colorBg(const Color & in)
{
  _colorBg = in;
  Color tmp(PIXEL_RGB, PIXEL_U8);
  convert(_colorBg, &tmp);
  Fl::background(tmp.u8(0), tmp.u8(1), tmp.u8(2));
}

void App::colorBg2(const Color & in)
{
  _colorBg2 = in;
  Color tmp(PIXEL_RGB, PIXEL_U8);
  convert(_colorBg2, &tmp);
  Fl::background2(tmp.u8(0), tmp.u8(1), tmp.u8(2));
}

void App::font(Fl_Font in)
{
  _font = in;
  //Fl_Tooltip::font(_font);
}

void App::fontBold(Fl_Font in)
{
  _fontBold = in;
}

void App::fontSize(int in)
{
  _fontSize = in;
  Fl_Tooltip::size(_fontSize);
}

void App::layoutSpacing(int in)
{
  _layoutSpacing = in;
}

void App::layoutMargin(int in)
{
  _layoutMargin = in;
}

void App::layoutWidgetMargin(int in)
{
  _layoutWidgetMargin = in;
}

void App::layoutButtonSize(int in)
{
  _layoutButtonSize = in;
}

void App::layoutThumbnailSize(int in)
{
  _layoutThumbnailSize = in;
}

void App::tooltips(bool in)
{
  if (in == _tooltips) return;
  _tooltips = in;
  tooltipsUpdate();
}

void App::tooltipsUpdate()
{
  if (_tooltips) Fl_Tooltip::enable();
  else Fl_Tooltip::disable();
}

void App::windowAdd(Fl_Window * in)
{
  DJ_DBG_FNC("dj::App::windowAdd");

  _windowList.add(in);
}

void App::windowDel(Fl_Window * in)
{
  DJ_DBG_FNC("dj::App::windowDel");
  
  _windowList.del(find(_windowList, in));
}

void App::imageFactoryInit()
{
  DJ_DBG_FNC("dj::App::imageFactoryInit");
  
  imageOpWidget().pluginAdd(imageOpCoreWidgetList());
  imageOpWidget().pluginAdd(imageOpGenWidgetList());
  imageOpWidget().pluginAdd(imageOpColorWidgetList());
  imageOpWidget().pluginAdd(imageOpXformWidgetList());
  imageOpWidget().pluginAdd(imageOpCompWidgetList());
  
  List<ImageLoadWidget *> loadList;
  loadList += new ImageIoDpx::LoadWidget;
  _imageLoadWidgetFactory.pluginAdd(loadList);

  List<ImageSaveWidget *> saveList;
  saveList += new ImageIoTga::SaveWidget;
  saveList += new ImageIoSgi::SaveWidget;
  saveList += new ImageIoPpm::SaveWidget;
  saveList += new ImageIoDpx::SaveWidget;
  _imageSaveWidgetFactory.pluginAdd(saveList);
}

static void _prefsSetPlugin(const Plugin * in, Prefs * prefs)
{
  Prefs pluginPrefs(prefs, in->name());
  const StrList attrList = in->attrNameList();
  for (ConstStrListIt it = attrList; it.isValid(); ++it)
    pluginPrefs.set(it(), in->attr(it()));
}

void App::prefsSet()
{
  Prefs prefs(_prefs, "dj::App");
  
  // Image operations.
  //
  Prefs imageOpPrefs(&prefs, "imageOp");
  List<ImageOp *> imageOpList = this->imageOp().pluginList();
  for (ListIt<ImageOp *> it = imageOpList; it.isValid(); ++it)
    _prefsSetPlugin(it(), &imageOpPrefs);
  
  // Image I/O.
  //
  Prefs imageLoadPrefs(&prefs, "imageLoad");
  List<ImageLoad *> imageLoadList = this->imageLoad().pluginList();
  for (ListIt<ImageLoad *> it = imageLoadList; it.isValid(); ++it)
    _prefsSetPlugin(it(), &imageLoadPrefs);
  Prefs imageSavePrefs(&prefs, "imageSave");
  List<ImageSave *> imageSaveList = this->imageSave().pluginList();
  for (ListIt<ImageSave *> it = imageSaveList; it.isValid(); ++it)
    _prefsSetPlugin(it(), &imageSavePrefs);
  
  // File browser.
  //
  _fileBrowser->prefs("fileBrowser", &prefs);
 
  // Miscellaneous.
  //
  prefs.set("tooltips", _tooltips);
  _prefsInit = true;
  prefs.set("prefsInit", _prefsInit);
}

static void _prefsGetPlugin(Plugin * in, const Prefs & prefs)
{
  Prefs pluginPrefs(prefs, in->name());
  const StrList attrList = in->attrNameList();
  StrList data;
  for (ConstStrListIt it = attrList; it.isValid(); ++it)
    if(pluginPrefs.get(it(), &data))
      in->attr(it(), data);
}

void App::prefsGet()
{
  Prefs prefs(_prefs, "dj::App");
  
  // Image operations.
  //
  Prefs imageOpPrefs(prefs, "imageOp");
  List<ImageOp *> imageOpList = this->imageOp().pluginList();
  for (ListIt<ImageOp *> it = imageOpList; it.isValid(); ++it)
    _prefsGetPlugin(it(), imageOpPrefs);
  
  // Image I/O.
  //
  Prefs imageLoadPrefs(prefs, "imageLoad");
  List<ImageLoad *> imageLoadList = this->imageLoad().pluginList();
  for (ListIt<ImageLoad *> it = imageLoadList; it.isValid(); ++it)
    _prefsGetPlugin(it(), imageLoadPrefs);
  Prefs imageSavePrefs(prefs, "imageSave");
  List<ImageSave *> imageSaveList = this->imageSave().pluginList();
  for (ListIt<ImageSave *> it = imageSaveList; it.isValid(); ++it)
    _prefsGetPlugin(it(), imageSavePrefs);
  
  // File browser.
  //
  _fileBrowser->prefs("fileBrowser", prefs);

  // Miscellaneous.
  //
  prefs.get("tooltips", &_tooltips, _tooltips);
  prefs.get("prefsInit", &_prefsInit, _prefsInit);
}

}
