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

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

//#define DJ_DBG
#include "window.h"
#include "widget.h"
#include "app.h"
#include <djImageOpStack.h>
#include <djMenuWidget.h>
#include <djImageOpStackWidget.h>

namespace djvlut {

Window::Window() :
  dj::Window("djvlut"),
  _menuItems(0),
  _callbacks(true)
{
  DJ_DBG_FNC("Window::Window");
  
  // Widgets.
  //
  color(FL_BACKGROUND2_COLOR);
  _widget = new ImageOpStackWidget;
  _vlutWidget = new VlutWidget;
  _menuItems = new MenuItems;
  _menubar = new MenubarWidget;
  
  // Layout.
  //
  VLayout * layout = new VLayout(this);
  layout->spacing(0);
  layout->margin(0);
  layout->add(_menubar);
  layout->add(_vlutWidget);
  layout->add(_widget);
  layout->stretch(_widget);
  
  // Initialize.
  //
  _widget->set(&djvlutApp->imageOpStack());
  menuUpdate();
  size(Vec2i(300, 280));
  
  // Callbacks.
  //
  _widget->updateSig().set(this, updateCallback);
  _widget->stackActiveSig().set(this, stackActiveCallback);
  _widget->stackUpdateSig().set(this, stackUpdateCallback);
  closeSig().set(this, closeCallback);
}

Window::~Window()
{
  DJ_DBG_FNC("Window::~Window");
 
  die();
  if (_menuItems) delete _menuItems;
}

void Window::die()
{
  inputDialogDel(this, stackNameCallback);
  fileBrowserDel(this, fileSaveCallback);
}

void Window::vlut(const Image * in)
{
  _vlutWidget->set(in);
}

void Window::vlutPreviewCallback()
{
  if (! _callbacks) return;
  djvlutApp->vlutPreview(! djvlutApp->vlutPreview());
}

void Window::stackActive(int in)
{
  _widget->stackActive(in);
}

void Window::fileSaveCallback(const Str & in)
{
  if (! _callbacks) return;
  djvlutApp->fileSave(in);
}

void Window::fileSaveCallback(bool)
{
  if (! _callbacks) return;
  fileBrowser(this, fileSaveCallback);
}

void Window::fileSaveCallback() { fileSaveCallback(true); }

void Window::prefsCallback()
{
  if (! _callbacks) return;
  djvlutApp->prefsDialog();
}

void Window::aboutCallback()
{
  if (! _callbacks) return;
  djvlutApp->aboutDialog();
}

void Window::exitCallback()
{
  if (! _callbacks) return;
  djvlutApp->exit();
}

void Window::updateCallback(bool)
{
  if (! _callbacks) return;
  djvlutApp->vlutUpdate();
  menuUpdate();
}

int Window::stackActive() const
{
  return _widget->stackActive();
}

void Window::stackActiveCallback(int in)
{
  if (! _callbacks) return;
  menuUpdate();
  djvlutApp->vlutUpdate();
}

void Window::stackActiveCallback()
{
  if (! _callbacks) return;
  _widget->stackActive(dj::find(_stackMenuId, _menubar->value()));
  djvlutApp->vlutUpdate();
}

void Window::stackNewCallback()
{
  if (! _callbacks) return;
  _widget->stackNew();
}

void Window::stackCopyCallback()
{
  if (! _callbacks) return;
  _widget->stackCopy(_widget->stackActive());
}

void Window::stackDelCallback()
{
  if (! _callbacks) return;
  _widget->stackDel(_widget->stackActive());
}

void Window::stackNameCallback(const Str & in)
{
  if (! _callbacks) return;
  _widget->stackName(in, _widget->stackActive());
}

void Window::stackNameCallback()
{
  if (! _callbacks) return;
  const int stack = _widget->stackActive();
  if (-1 == stack) return;
  inputDialog(
    "Stack name:", djvlutApp->imageOpStack().stackName(stack),
    this, stackNameCallback
  );
}

void Window::stackLeftCallback()
{
  if (! _callbacks) return;
  _widget->stackLeft(_widget->stackActive());
}

void Window::stackRightCallback()
{
  if (! _callbacks) return;
  _widget->stackRight(_widget->stackActive());
}

void Window::stackUpdateCallback(int in)
{
  if (! _callbacks) return;
  djvlutApp->vlutUpdate();
}

void Window::opNewCallback()
{
  if (! _callbacks) return;
  const int id = dj::find(_opMenuId, _menubar->value());
  _widget->opNew(imageOpList()[id], _widget->stackActive());
}

void Window::opCopyCallback()
{
  if (! _callbacks) return;
  _widget->opCopy(_widget->opActive(), _widget->stackActive());
}

void Window::opDelCallback()
{
  if (! _callbacks) return;
  _widget->opDel(_widget->opActive(), _widget->stackActive());
}

void Window::opLeftCallback()
{
  if (! _callbacks) return;
  _widget->opLeft(_widget->opActive(), _widget->stackActive());
}

void Window::opRightCallback()
{
  if (! _callbacks) return;
  _widget->opRight(_widget->opActive(), _widget->stackActive());
}

void Window::closeCallback(bool)
{
  djvlutApp->exit();
}

void Window::widgetUpdate()
{
  _callbacks = false;
  
  _widget->widgetUpdate();
  menuUpdate();
  
  _callbacks = true;
}

void Window::menuUpdate()
{
  _callbacks = false;

  _menuItems->del();
  
  // File menu.
  //
  _menuItems->add("&File", 0, 0, 0, FL_SUBMENU);
  _menuItems->add(
    "&Preview", ' ', vlutPreviewCallback, this,
    FL_MENU_TOGGLE | (djvlutApp->vlutPreview() ? FL_MENU_VALUE : 0)
  );
  _menuItems->add(
    "&Save", FL_CTRL + 's', fileSaveCallback, this, FL_MENU_DIVIDER
   );
  _menuItems->add("&Preferences", 0, prefsCallback, this);
  _menuItems->add("&About", 0, aboutCallback, this, FL_MENU_DIVIDER);
  _menuItems->add("E&xit", FL_CTRL + 'q', exitCallback, this);
  _menuItems->end();
  
  // Stack menu.
  //
  _menuItems->add("&Stack", 0, 0, 0, FL_SUBMENU);
  
  _menuItems->add("&Stack", 0, 0, 0, FL_SUBMENU);
  _stackMenuId.del();
  for (int i = 0; i < djvlutApp->imageOpStack().stackSize(); ++i)
    _stackMenuId += _menuItems->add(
      djvlutApp->imageOpStack().stackName(i),
      i <= 9 ? ('1' + i) : 0, stackActiveCallback, this,
      FL_MENU_RADIO | (i == _widget->stackActive() ? FL_MENU_VALUE : 0)
    );
  _menuItems->end();
  
  _menuItems->add("&New", FL_CTRL + 'n', stackNewCallback, this);
  _menuItems->add("&Copy", FL_SHIFT + FL_CTRL + 'c', stackCopyCallback, this);
  _menuItems->add("&Rename", FL_CTRL + 'r', stackNameCallback, this);
  _menuItems->add(
    "D&elete", FL_SHIFT + FL_Delete, stackDelCallback, this,
    FL_MENU_DIVIDER
  );
  _menuItems->add("Move &Left", FL_SHIFT + '[', stackLeftCallback, this);
  _menuItems->add("Move R&ight", FL_SHIFT + ']', stackRightCallback, this);
  _menuItems->end();
  
  // Operation menu.
  //
  _menuItems->add("&Operation", 0, 0, 0, FL_SUBMENU);
  _menuItems->add("&New", 0, 0, 0, FL_SUBMENU);
  _opMenuId.del();
  const StrList imageOpList = djvlut::imageOpList();
  for (ConstStrListIt it = imageOpList; it.isValid(); ++it)
    _opMenuId += _menuItems->add(it(), 0, opNewCallback, this);
  _menuItems->end();
  _menuItems->add("&Copy", FL_CTRL + 'c', opCopyCallback, this);
  _menuItems->add(
    "D&elete", FL_Delete, opDelCallback, this,
    FL_MENU_DIVIDER
  );
  _menuItems->add("Move &Left", '[', opLeftCallback, this);
  _menuItems->add("Move &Right", ']', opRightCallback, this);
  _menuItems->end();
  
  _menuItems->end();
  _menuItems->set(_menubar);
  
  _callbacks = true;
}

}
