/*------------------------------------------------------------------------------
 src/bin/djvlut/app.cxx

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

//#define DJ_DBG
#include "app.h"
#include "widget.h"
#include "window.h"
#include "prefsDialog.h"
#include "aboutDialog.h"
#include <djImageOpGen.h>
#include <djImageOpStackWidget.h>
#include <stdlib.h>

namespace djvlut {

App::App(int & argc, char ** argv) :
  dj::App("djvlut", argc, argv),
  _vlutName(getenv("DISPLAY")), _vlutPreview(false), _vlutSave(0),
  _saveWindowGeom(true),
  _window(0), _prefsDialog(0), _aboutDialog(0),
  _callbacks(true)
{
  DJ_DBG_FNC("App::App");
  
  // Command line.
  //
  StrList argList;
  for (int i = 1; i < argc; ++i) {
    const Str it = argv[i];
    if (Str("-help") == it || Str("-h") == it) { help(); return; }
    else if (Str("-about") == it) { about(); return; }
    else argList += it;
  }
  const Str err = cmdln(argList);
  if (! err.isNull()) {
    error(Str("Error parsing command line \"%1\".").arg(err));
    exitValue(1);
    return;
  }
  valid(true);

  // Widgets.
  //
  _window = new Window;
  _prefsDialog = new PrefsDialog;
  _aboutDialog = new AboutDialog;

  // Initialize.
  //
  prefsGet();
  
  _window->show();
  
  _vlutInfo.set(Vec2i(256, 1), Pixel(PIXEL_RGB, PIXEL_U8));
  ImageIoInfo info;
  ImageLoad * load = dj::imageLoad(_vlutName, &info, "VLUT");
  if (! load) {
    error(Str("Cannot open video lookup table \"%1\".").arg(_vlutName));
  } else {
    _vlutInfo.set(info.size(), info.pixel());
    delete load;
    _vlutSave = dj::imageSave(_vlutName, _vlutInfo, "VLUT");
    if (! _vlutSave)
      error(Str("Cannot open video lookup table \"%1\".").arg(_vlutName));
  }
  vlutUpdate();
}

App::~App()
{
  DJ_DBG_FNC("App::~App");
  
  if (isValid()) prefsSet();

  if (_window) delete _window;
  if (_prefsDialog) delete _prefsDialog;
  if (_aboutDialog) delete _aboutDialog;
  
  if (_vlutSave) delete _vlutSave;
}

void App::vlutPreview(bool in)
{
  if (in == _vlutPreview) return;
  
  DJ_DBG_FNC("App::vlutPreview");
  DJ_DBG_PRN("in = " << in);
  
  _vlutPreview = in;
  vlutUpdate();
}

void App::vlutUpdate()
{
  DJ_DBG_FNC("App::vlutUpdate");
  DJ_DBG_PRN("vlut = " << _vlut);
  
  Image linear = ImageOpGradient::work(
    _vlutInfo.size(), _vlutInfo.pixel(),
    Vec2i(0, 0), Vec2i(_vlutInfo.width() - 1, 0),
    Color(0.0), Color(1.0)
  );
  
  Image lut = linear;
  const int stackActive = _window->stackActive();
  if (stackActive != -1) {
    const List<ImageOp *> & stack = _imageOpStack.stack(stackActive);
    for (ConstListIt<ImageOp *> it = stack; it.isValid(); ++it) {
      DJ_DBG_PRN("operation = " << it()->name());
      ImageOp::InputList inputs;
      inputs += &lut;
      lut = it()->work(inputs);
    }
  }
  
  _vlut = lut;
  if (! _vlutPreview) {
    _window->vlut(0);
    if (_vlutSave) _vlutSave->set(_vlut);
  } else {
    _window->vlut(&_vlut);
    if (_vlutSave) _vlutSave->set(linear);
  }
}

void App::fileSave(const Str & in)
{
  DJ_DBG_FNC("App::fileSave");
  DJ_DBG_PRN("in = " << in);
  
  ImageIoInfo info;
  info.size(_vlut.size());
  info.pixel(_vlut.pixel());
  ImageSave * save = dj::imageSave(in, info);
  if (! save) {
    error(Str("Cannot open \"%1\".").arg(in));
    return;
  }
  
  if (! save->set(_vlut))
    error(Str("Cannot save \"%1\".").arg(in));

  delete save;
}
  
void App::prefsDialog()
{
  _prefsDialog->show();
}

void App::prefsSet()
{
  DJ_DBG_FNC("App::prefsSet");
  
  Prefs prefsThis(prefs(), "djvlut");
  
  prefsThis.set("vlutPreview", _vlutPreview);

  dj::prefs(_imageOpStack, "imageOpStack", &prefsThis);
  prefsThis.set("active", _window->stackActive());
  
  prefsThis.set("saveWindowGeom", _saveWindowGeom);
  prefsThis.del("geom");
  if (_saveWindowGeom)
    prefsThis.set("geom", deflateStr(_window->geom()));
}

void App::prefsGet()
{
  DJ_DBG_FNC("App::prefsGet");
  
  Prefs prefsThis(prefs(), "djvlut");
  StrList data;
  
  prefsThis.get("vlutPreview", &_vlutPreview, _vlutPreview);

  if (! prefsInit()) imageOpDefault();
  dj::prefs(&_imageOpStack, "imageOpStack", prefsThis);
  _window->widgetUpdate();
  int active = -1;
  prefsThis.get("active", &active, active);
  _window->stackActive(active);
  
  prefsThis.get("saveWindowGeom", &_saveWindowGeom, _saveWindowGeom);
  if (prefsThis.get("geom", &data)) {
    Box2i geom;
    inflateStr(data, &geom);
    _window->resize(geom.x(), geom.y(), geom.width(), geom.height());
  }
  
  _prefsDialog->widgetUpdate();
}

void App::aboutDialog()
{
  _aboutDialog->show();
}

void App::saveWindowGeom(bool in)
{
  _saveWindowGeom = in;
}

const Str App::cmdln(StrList & in)
{
  // Options.
  //
  StrList argList;
  while (in.size()) {
    const Str it = in[0];
    in.pop();
    
    if (0) {
      
    } else argList += it;
  }
  
  // Arguments.
  //
  if (argList.size() > 1) return argList[1];
  if (argList.size() > 0) _vlutName = argList[0];
  
  return Str();
}

static const char helpStr [] =
"\n"
"djvlut\n"
"------\n"
"\n"
"Video lookup table tool.\n"
"\n"
"Usage\n"
"-----\n"
"\n"
"djvlut [input] [option]...\n"
"\n"
"Arguments\n"
"---------\n"
"\n"
"input - Video lookup table name. Default: %1.\n"
"\n"
"General Options\n"
"---------------\n"
"\n"
"-help, -h - Display help message.\n"
"\n"
"-about - Display about message.\n";

void App::help()
{
  printFormatted(Str(helpStr).arg(_vlutName));
}

}

int main(int argc, char ** argv)
{
  DJ_DBG_LOG();
  return djvlut::App(argc, argv).exec();
}
