/*------------------------------------------------------------------------------
 src/bin/djview/widget.cxx

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

//#define DJ_DBG
#include "widget.h"
#include "app.h"
#include <djLabelWidget.h>
#include <djButtonWidget.h>
#include <FL/Fl.H>
#include <FL/Fl_Output.H>
#include <FL/fl_draw.H>
#include <FL/x.H>
#include <FL/gl.h>

namespace djview {

FrameSliderWidget::FrameSliderWidget() :
  _inPoint(false), _outPoint(false),
  _inFrame(0), _outFrame(0)
{}

void FrameSliderWidget::set(int in)
{
  IntSliderWidget::set(
    playbackFrame(
      in, min(), max(), _inPoint, _outPoint, _inFrame, _outFrame, false
    )
  );
}

void FrameSliderWidget::inOutPoint(bool inPoint, bool outPoint)
{
  _inPoint = inPoint;
  _outPoint = outPoint;
  redraw();
}

void FrameSliderWidget::inOutFrame(int inFrame, int outFrame)
{
  _inFrame = inFrame;
  _outFrame = outFrame;
  redraw();
}

void FrameSliderWidget::drawBackground(const Box2i & in)
{
  IntSliderWidget::drawBackground(in);

  if (_inPoint || _outPoint && (_inPoint < _outPoint)) {
  
    const double range = max() - min();
    const double v0 =
      _inPoint ? ((dj::max(_inFrame, min()) - min()) / range) : 0.0;
    const double v1 =
      _outPoint ? ((dj::min(_outFrame, max()) - min()) / range) : 1.0;
    
    fl_color(FL_YELLOW);
    fl_rectf(
      int(in.x() + in.width() * v0), in.y(),
      int(in.width() * (v1 - v0) + 1), in.height()
    );
  }
}

PlaybackSpeedDisplayWidget::PlaybackSpeedDisplayWidget() :
  _droppedFrames(false)
{}

void PlaybackSpeedDisplayWidget::set(double in)
{
  TextDisplayWidget::set(toStr(in, 3));
}

void PlaybackSpeedDisplayWidget::droppedFrames(bool in)
{
  if (in == _droppedFrames) return;
  _droppedFrames = in;
  if (_droppedFrames) widget()->textcolor(FL_YELLOW);
  else widget()->textcolor(FL_FOREGROUND_COLOR);
  redraw();
}

ViewWidget::ViewWidget() :
  _hud(false),
  _playbackFrame(0), _playbackFrameStart(0), _playbackFrameEnd(0),
  _playbackSpeed(0.0), _playbackSpeedReal(0.0),
  _playbackDroppedFrames(false)
{
  labelfont(dj::fontBold());
  labelsize(dj::fontSize());
}

void ViewWidget::toolMode(bool in)
{
  _toolMode = in;
}

void ViewWidget::hud(bool in)
{
  _hud = in;
}

void ViewWidget::fileName(const Str & in)
{
  _fileName = in;
}

void ViewWidget::pixelDataInfo(const PixelDataInfo & in)
{
  _pixelDataInfo = in;
}

void ViewWidget::imageTagList(const ImageTagList & in)
{
  _imageTagList = in;
}

void ViewWidget::playbackFrame(int in, int start, int end)
{
  _playbackFrame = in;
  _playbackFrameStart = start;
  _playbackFrameEnd = end;
}

void ViewWidget::playbackSpeed(double in, double real, bool droppedFrames)
{
  _playbackSpeed = in;
  _playbackSpeedReal = real;
  _playbackDroppedFrames = droppedFrames;
}

void ViewWidget::draw()
{
  ImageViewWidget::draw();

  DJ_DBG_FNC("ViewWidget::draw");
  
  if (_hud) {

    gl_font(labelfont(), labelsize());
  
    // Image information.
    //
    int x = layoutMargin(), y = h() - gl_height() - layoutMargin();
    drawText(_fileName, Vec2i(x, y + gl_descent()));
    y -= gl_height();
    
    Str str = Str("%1x%2:%3").
      arg(_pixelDataInfo.size().x()).arg(_pixelDataInfo.size().y()).
      arg(dj::aspect(_pixelDataInfo.size()), 0, 2);
    drawText(str, Vec2i(x, y + gl_descent()));
    y -= gl_height();
    
    str = Str("%1 %2").
      arg(pixelFormatStr()[_pixelDataInfo.pixel().format()]).
      arg(pixelTypeStr()[_pixelDataInfo.pixel().type()]);
    drawText(str, Vec2i(x, y + gl_descent()));
    
    // Image tags.
    //
    StrList tagList;
    StrList keyList = _imageTagList.keyList();
    for (StrListIt it = keyList; it.isValid(); ++it)
      tagList += Str("%1: %2").arg(it()).arg(_imageTagList[it()]);

    int textW = 0;
    for (StrListIt it = tagList; it.isValid(); ++it)
      textW = max(ceil(gl_width(it().toAscii())), textW);
      
    y = gl_height() * (tagList.size() - 1) + layoutMargin();
    for (StrListIt it = tagList; it.isValid(); ++it) {
      drawText(it(), Vec2i(x, y + gl_descent()));
      y -= gl_height();
    }
    
    // Playback.
    //
    x = w() - layoutMargin();
    y = h() - gl_height() - layoutMargin();
    str = Str("%1/%2-%3").
      arg(_playbackFrame).arg(_playbackFrameStart).arg(_playbackFrameEnd);
    drawText(str, Vec2i(x - ceil(gl_width(str.toAscii())), y + gl_descent()));
    y -= gl_height();

    str = Str("/%1").arg(_playbackSpeedReal, 0, 2);
    x -= ceil(gl_width(str.toAscii()));
    drawText(
      str, Vec2i(x, y + gl_descent()),
      _playbackDroppedFrames ? FL_YELLOW : FL_WHITE
    );
    str = Str("%1").arg(_playbackSpeed, 0, 2);
    x -= ceil(gl_width(str.toAscii()));
    drawText(str, Vec2i(x, y + gl_descent()));
  }
}

void ViewWidget::drawText(
  const Str & in, const Vec2i & position, const Fl_Color & color
) {
  glColor3f(0, 0, 0);
  gl_draw(in.toAscii(), position.x() + 1, position.y() - 1);
  gl_color(color);
  gl_draw(in.toAscii(), position.x(), position.y());
}

int ViewWidget::handle(int in)
{
  if (_toolMode) {

    const Vec2i mouse = Vec2i(Fl::event_x(), h() - 1 - Fl::event_y());
    switch (in) {
  
      case FL_PUSH:
        take_focus();
      case FL_DRAG:
        _mouse = mouse;
        _toolSig.emit(true);
        return 1;
    }
  }
  
  return ImageViewWidget::handle(in);
}

}
