/*******************************************************************************
*                         Goggles Music Manager                                *
********************************************************************************
*           Copyright (C) 2006-2010 by Sander Jansen. All Rights Reserved      *
*                               ---                                            *
* This program is free software: you can redistribute it and/or modify         *
* it under the terms of the GNU General Public License as published by         *
* the Free Software Foundation, either version 3 of the License, or            *
* (at your option) any later version.                                          *
*                                                                              *
* 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, see http://www.gnu.org/licenses.           *
********************************************************************************/
#include "icons.h"
#include "gmdefs.h"
#include <FXPNGIcon.h>
#include <FXPNGImage.h>
#include "GMRemote.h"
#include "GMWindow.h"
#include "GMList.h"
#include "GMSource.h"
#include "GMPlayerManager.h"
#include "GMIconTheme.h"

#ifdef HAVE_COMPACT_REMOTE

// Map
FXDEFMAP(GMRemote) GMRemoteMap[]={
  FXMAPFUNC(SEL_PAINT,0,GMRemote::onPaint),
  FXMAPFUNC(SEL_MOTION,0,GMRemote::onMotion),
  FXMAPFUNC(SEL_MOUSEWHEEL,0,GMRemote::onMouseWheel),
  FXMAPFUNC(SEL_ENTER,0,GMRemote::onEnter),
  FXMAPFUNC(SEL_LEAVE,0,GMRemote::onLeave),
  FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,GMRemote::onLeftBtnPress),
  FXMAPFUNC(SEL_LEFTBUTTONRELEASE,0,GMRemote::onLeftBtnRelease),
  FXMAPFUNC(SEL_RIGHTBUTTONPRESS,0,GMRemote::onRightBtnPress),
  FXMAPFUNC(SEL_RIGHTBUTTONRELEASE,0,GMRemote::onRightBtnRelease),
  FXMAPFUNC(SEL_QUERY_TIP,0,GMRemote::onQueryTip),
  FXMAPFUNC(SEL_COMMAND,GMRemote::ID_SHOW_MANAGER,GMRemote::onCmdShowManager),
  FXMAPFUNC(SEL_TIMEOUT,GMRemote::ID_RESTORE_PROGRESS,GMRemote::onRestoreProgress),
  FXMAPFUNC(SEL_TIMEOUT,GMRemote::ID_SINGLE_CLICK,GMRemote::onSingleClick),

  };

// Implementation
FXIMPLEMENT(GMRemote,FXTopWindow,GMRemoteMap,ARRAYNUMBER(GMRemoteMap))

// ShutterBug main window
GMRemote::GMRemote(FXApp* a,FXObject*tgt,FXSelector msg):FXTopWindow(a,FXString::null,NULL,NULL,0, 0,0,0,0, 0,0,0,0,0,0){
  flags|=FLAG_ENABLED;
  setTarget(tgt);
  setSelector(msg);
  main=logo=logohover=NULL;
  spotx=0;
  spoty=0;
  progress=0;
  showVolume=FALSE;
  tip="Stopped";
  }

// Destroy main window
GMRemote::~GMRemote(){
  getApp()->removeTimeout(this,GMRemote::ID_RESTORE_PROGRESS);
  getApp()->removeTimeout(this,GMRemote::ID_SINGLE_CLICK);
  delete logo;
  delete logohover;
  }


void GMRemote::writeRegistry(){
  getApp()->reg().writeIntEntry("window","remote-x",getX());
  getApp()->reg().writeIntEntry("window","remote-y",getY());
  }

// Create and show window
void GMRemote::create(){
  FXShell::create();
  FXint x = getApp()->reg().readIntEntry("window","remote-x",getX());
  FXint y = getApp()->reg().readIntEntry("window","remote-y",getY());
  move(x,y);
  show();
  }


static void grayscale(FXImage * icon){
  FXColor color;
  FXfloat luminance;
  for (FXint y=0;y<icon->getHeight();y++){
    for (FXint x=0;x<icon->getWidth();x++){
      color=icon->getPixel(x,y);
      if (FXALPHAVAL(color)>0) {
        luminance = (((FXREDVAL(color)*0.3f)+(FXGREENVAL(color)*0.59f)+(FXBLUEVAL(color)*0.11f)));
        icon->setPixel(x,y,FXRGBA(luminance,luminance,luminance,FXALPHAVAL(color)));
        }
      }
    }
  }


void GMRemote::show() {
  logo=new FXPNGIcon(getApp(),remote_png);
  logohover=new FXPNGIcon(getApp(),remote_png);
  grayscale(logo);
  logo->create();
  logohover->create();
  main=logo;
  resize(getDefaultWidth(),getDefaultHeight());
  setShape(logo); // Set window shape based on icon shape mask
  FXShell::show();
  }

void GMRemote::hide(){
  FXShell::hide();
  delete logo;
  delete logohover;
  logo=NULL;
  logohover=NULL;
  main=NULL;
  }


void GMRemote::reset(){
  setToolTip("Stopped");
  }

void GMRemote::updateCover(FXImage *) {
  }

void GMRemote::display(const GMTrack &track){
  setToolTip(GMStringVal(track.no)+". "+track.title+"\n"+track.artist+"\n"+track.album);
  }


void GMRemote::elapsed_time(FXint,FXint,FXint,FXint p,FXbool playing){
  if (playing)
    progress=p;
  else
    progress=0;
  update();
  }

// Get default width
FXint GMRemote::getDefaultWidth(){
  if (logo) return logo->getWidth();
  else return 1;
  }


// Get default height
FXint GMRemote::getDefaultHeight(){
  if (logo) return logo->getHeight();
  else return 1;
  }

bool GMRemote::doesOverrideRedirect() const { return TRUE; }


void GMRemote::setProgress(FXint p){
  progress=p;
  update();
  }

static void drawProgress(FXDC & dc,FXint progress,FXint total){
  FXuint filled = (FXuint) (((double)progress * 55.0) / (double) total);
  if (filled>0){
    dc.fillRectangle(10,64,filled,3);
    }
  }

// Handle repaint
long GMRemote::onPaint(FXObject*,FXSelector,void* ptr){
  register FXEvent *event=(FXEvent*)ptr;
  FXDCWindow dc(this,event);
//  dc.setForeground(FXRGB(0,0,0));
//  dc.drawRectangle(0,0,width-1,height-1);

  if (main) {
    dc.drawIcon(main,0,0);
    dc.drawRectangle(9,63,56,4);
    if (showVolume) {
      dc.setForeground(FXRGB(134,204,134));
      drawProgress(dc,volume,100);
      }
    else {
      dc.setForeground(FXRGB(74,121,205));
      drawProgress(dc,progress,65535);
      }
    }
  else {
    dc.setForeground(backColor);
    dc.fillRectangle(0,0,width,height);
    }
  return 1;
  }

// Mouse motion
long GMRemote::onMotion(FXObject*,FXSelector,void* ptr){
  FXEvent *event=(FXEvent*)ptr;
  if(flags&FLAG_PRESSED){
    move(event->root_x-spotx,event->root_y-spoty);
    return 1;
    }
  return 0;
  }

// Mouse wheel
long GMRemote::onMouseWheel(FXObject*,FXSelector,void* ptr){
  register FXEvent *event=(FXEvent*)ptr;
  if (!showVolume){
    volume = GMPlayerManager::instance()->volume();
    showVolume=TRUE;
    }
  register FXint p=volume+(event->code*10)/120;
  if(p<0)   p=0;
  if(p>100) p=100;
  if(volume!=p){
    volume=p;
    GMPlayerManager::instance()->volume(volume);
    GMPlayerManager::instance()->getMainWindow()->update_volume_display(volume);
    update();
    }
  getApp()->addTimeout(this,ID_RESTORE_PROGRESS,TIME_SEC(2));
  return 1;
  }

long GMRemote::onRestoreProgress(FXObject*,FXSelector,void*){
  showVolume=FALSE;
  update();
  return 1;
  }

// Left button pressed
long GMRemote::onLeftBtnPress(FXObject*,FXSelector,void* ptr){
  FXEvent *event=(FXEvent*)ptr;
  if (event->click_count==1){
    grab();
    spotx=event->win_x;
    spoty=event->win_y;
    flags|=FLAG_PRESSED;
    }
  return 1;
  }

// Left button released
long GMRemote::onLeftBtnRelease(FXObject*,FXSelector,void*ptr){
  FXEvent *event=(FXEvent*)ptr;
  ungrab();
  flags&=~FLAG_PRESSED;
  if (event->moved) return 1;
  if (event->click_count==1){
    getApp()->addTimeout(this,ID_SINGLE_CLICK,getApp()->getClickSpeed());
    }
  else if(event->click_count==2){
    getApp()->removeTimeout(this,ID_SINGLE_CLICK);
    close(true);
    }
  return 1;
  }

long GMRemote::onSingleClick(FXObject*,FXSelector,void*){
  if (GMPlayerManager::instance()->playing()) {
    if (GMPlayerManager::instance()->can_unpause())
      GMPlayerManager::instance()->unpause();
    else if (GMPlayerManager::instance()->can_next())
      GMPlayerManager::instance()->next();
    else
      getApp()->beep();
    }
  else if (GMPlayerManager::instance()->can_play()) {
    GMPlayerManager::instance()->play();
    }
  else {
    getApp()->beep();
    }
  return 1;
  }

// Left button pressed
long GMRemote::onRightBtnPress(FXObject*,FXSelector,void*){
  grab();
  flags|=FLAG_PRESSED;
  return 1;
  }

// Left button released
long GMRemote::onRightBtnRelease(FXObject*,FXSelector,void* ptr){
  FXEvent *event=(FXEvent*)ptr;
  ungrab();
  flags&=~FLAG_PRESSED;
  if(event->moved) return 1;
  FXMenuPane filemenu(this);

  new FXMenuCommand(&filemenu,tr("&Next"),GMIconTheme::instance()->icon_next,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_NEXT);
  new FXMenuCommand(&filemenu,tr("P&revious"),GMIconTheme::instance()->icon_prev,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_PREV);
  new FXMenuCommand(&filemenu,tr("&Play"),GMIconTheme::instance()->icon_play,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_PLAYPAUSEMENU);
  new FXMenuCommand(&filemenu,tr("&Stop"),GMIconTheme::instance()->icon_stop,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_STOP);
  new FXMenuSeparator(&filemenu);
  new FXMenuCommand(&filemenu,tr("Show Browser"),NULL,this,ID_SHOW_MANAGER);
  new FXMenuCommand(&filemenu,tr("Quit"),GMIconTheme::instance()->icon_exit,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_QUIT);
  filemenu.create();
  filemenu.forceRefresh();
  ewmh_change_window_type(&filemenu,WINDOWTYPE_POPUP_MENU);
  filemenu.popup(NULL,event->root_x,event->root_y);
  getApp()->runModalWhileShown(&filemenu);
  return 1;
  }

long GMRemote::onEnter(FXObject*obj,FXSelector sel,void* ptr){
  FXShell::onEnter(obj,sel,ptr);
  main = logohover;
  update();
  return 1;
  }

long GMRemote::onLeave(FXObject*obj,FXSelector sel,void* ptr){
  FXShell::onLeave(obj,sel,ptr);
  main = logo;
  update();
  return 1;
  }


long GMRemote::onCmdShowManager(FXObject*,FXSelector,void*){
  GMPlayerManager::instance()->getMainWindow()->show();
  if (!GMPlayerManager::instance()->getPreferences().gui_always_show_remote){
    showVolume=FALSE;
    close(true);
    }
  return 1;
  }

long GMRemote::onQueryTip(FXObject*sender,FXSelector sel,void* ptr){
  if(FXShell::onQueryTip(sender,sel,ptr)) return 1;
  if((flags&FLAG_TIP) && !tip.empty() && !showVolume && !grabbed() ){
    sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&tip);
    return 1;
    }
  return 0;
  }

#else


// Map
FXDEFMAP(GMRemote) GMRemoteMap[]={
  FXMAPFUNC(SEL_UPDATE,   					GMRemote::ID_VOLUME_BUTTON,     GMRemote::onUpdVolumeButton),
  FXMAPFUNC(SEL_COMMAND,						GMRemote::ID_VOLUME_SLIDER,			GMRemote::onCmdVolume),
  FXMAPFUNC(SEL_CHANGED,						GMRemote::ID_VOLUME_SLIDER,			GMRemote::onCmdVolume),
  FXMAPFUNC(SEL_MOUSEWHEEL,					GMRemote::ID_VOLUME_BUTTON,     GMRemote::onCmdVolumeButton),
  FXMAPFUNC(SEL_MOUSEWHEEL,					0,															GMRemote::onCmdVolumeButton),
  };

// Implementation
FXIMPLEMENT(GMRemote,FXMainWindow,GMRemoteMap,ARRAYNUMBER(GMRemoteMap))

// ShutterBug main window
GMRemote::GMRemote(FXApp* a,FXObject * tgt,FXSelector msg):FXMainWindow(a,"Goggles Music Manager",NULL,NULL,DECOR_BORDER|DECOR_TITLE|DECOR_CLOSE,0,0,0,0,3,3,3,3,3,3){
  flags|=FLAG_ENABLED;
  setTarget(tgt);
  setSelector(msg);

  setIcon(GMIconTheme::instance()->icon_applogo);
  setMiniIcon(GMIconTheme::instance()->icon_applogo_small);

#if FOXVERSION < FXVERSION(1,7,17)
  FXFontDesc fontdescription;
  getApp()->getNormalFont()->getFontDesc(fontdescription);
#else
  FXFontDesc fontdescription = getApp()->getNormalFont()->getFontDesc();
#endif
  fontdescription.weight = FXFont::Bold;
  fontdescription.size  += 10;
  font_title = new FXFont(getApp(),fontdescription);
  font_title->create();

  img_default = new FXPNGImage(getApp(),about_png);
  img_default->scale(64,64,1);
  img_default->blend(getApp()->getBackColor());
  img_default->create();

  cover_label = new FXImageFrame(this,img_default,LAYOUT_SIDE_LEFT|FRAME_SUNKEN|LAYOUT_FIX_WIDTH|JUSTIFY_CENTER_X|JUSTIFY_CENTER_Y|LAYOUT_FILL_Y,0,0,64,64);
  cover_label->setBackColor(getApp()->getBackColor());

  if (GMPlayerManager::instance()->getMainWindow()->getSmallCover())
    cover_label->setImage(GMPlayerManager::instance()->getMainWindow()->getSmallCover());


  /// Popup Volume Menu
  volumecontrol = new FXPopup(this,POPUP_VERTICAL|FRAME_RAISED|FRAME_THICK|POPUP_SHRINKWRAP);
  volumeslider = new FXSlider(volumecontrol,this,GMRemote::ID_VOLUME_SLIDER,LAYOUT_FIX_HEIGHT|LAYOUT_FIX_WIDTH|SLIDER_VERTICAL|SLIDER_TICKS_RIGHT|SLIDER_TICKS_LEFT|SLIDER_INSIDE_BAR,0,0,20,100);
  volumeslider->setTickDelta(10);
  volumeslider->setRange(0,100);
  volumeslider->setIncrement(10);


  FXHorizontalFrame * buttons = new FXHorizontalFrame(this,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X,0,0,0,0,3,3,0,0);
  new FXButton(buttons,tr("\tStart Playback\tStart Playback"),GMIconTheme::instance()->icon_play,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_PLAYPAUSEMENU,BUTTON_TOOLBAR|FRAME_RAISED|ICON_ABOVE_TEXT);
  new FXButton(buttons,tr("\tStop Playback\tStop Playback"),GMIconTheme::instance()->icon_stop,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_STOP,BUTTON_TOOLBAR|FRAME_RAISED|ICON_ABOVE_TEXT);
  new FXVerticalSeparator(buttons,LAYOUT_FILL_Y|SEPARATOR_GROOVE);
  new FXButton(buttons,tr("\tPlay Previous Track\tPlay previous track."),GMIconTheme::instance()->icon_prev,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_PREV,BUTTON_TOOLBAR|FRAME_RAISED|ICON_ABOVE_TEXT);
  new FXButton(buttons,tr("\tPlay Next Track\tPlay next track."),GMIconTheme::instance()->icon_next,GMPlayerManager::instance()->getMainWindow(),GMWindow::ID_NEXT,BUTTON_TOOLBAR|FRAME_RAISED|ICON_ABOVE_TEXT);
  new FXVerticalSeparator(buttons,LAYOUT_FILL_Y|SEPARATOR_GROOVE);
  volumebutton = new FXMenuButton(buttons,tr("\tAdjust Volume\tAdjust Volume"),NULL,volumecontrol,MENUBUTTON_NOARROWS|MENUBUTTON_ATTACH_LEFT|MENUBUTTON_UP|MENUBUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_RIGHT);
  volumebutton->setTarget(this);
  volumebutton->setSelector(ID_VOLUME_BUTTON);

  new FXVerticalSeparator(buttons,LAYOUT_FILL_Y|SEPARATOR_GROOVE|LAYOUT_RIGHT);
  time_label =new FX7Segment(buttons,"--:--",SEVENSEGMENT_SHADOW|LAYOUT_CENTER_Y|LAYOUT_RIGHT);
  time_label->setCellWidth(10);
  time_label->setCellHeight(15);



  new FXSeparator(this,LAYOUT_SIDE_BOTTOM|SEPARATOR_GROOVE|LAYOUT_FILL_X);

  FXVerticalFrame * info = new FXVerticalFrame(this,LAYOUT_CENTER_Y|FRAME_NONE|LAYOUT_FILL_X,0,0,0,0,2,2,2,2,0,0);
//  title_label = new FXTextField(info,30,NULL,0,FRAME_NONE|TEXTFIELD_LIMITED,0,0,0,0,0,0,0,0);
  title_label = new FXLabel(info,FXString::null,NULL,LABEL_NORMAL,0,0,0,0,0,0,0,0);
//  title_label->disable();
//  title_label->setText("Other Side of The Game");
  title_label->setFont(font_title);
  artistalbum_label = new FXLabel(info,FXString::null,NULL,LABEL_NORMAL,0,0,0,0,0,0,0,0);

  getAccelTable()->addAccel(parseAccel("F11"),this,FXSEL(SEL_CLOSE,0));
  getAccelTable()->addAccel(parseAccel("Ctrl-W"),this,FXSEL(SEL_CLOSE,0));
  getAccelTable()->addAccel(parseAccel("Ctrl-Q"),GMPlayerManager::instance()->getMainWindow(),FXSEL(SEL_COMMAND,GMWindow::ID_QUIT));


  GMIconTheme::instance()->loadSmall(icon_volume_high,"audio-volume-high.png",FXApp::instance()->getBaseColor());
  GMIconTheme::instance()->loadSmall(icon_volume_medium,"audio-volume-medium.png",FXApp::instance()->getBaseColor());
  GMIconTheme::instance()->loadSmall(icon_volume_low,"audio-volume-low.png",FXApp::instance()->getBaseColor());
  GMIconTheme::instance()->loadSmall(icon_volume_muted,"audio-volume-muted.png",FXApp::instance()->getBaseColor());


  update_volume_display(GMPlayerManager::instance()->volume());
  reset();
  }

// Destroy main window
GMRemote::~GMRemote(){
  volumeslider->setTarget(NULL);
  volumeslider->setSelector(0);
  volumebutton->setMenu(NULL);
  }

void GMRemote::writeRegistry(){
  getApp()->reg().writeIntEntry("window","remote-x",getX());
  getApp()->reg().writeIntEntry("window","remote-y",getY());
  }

void GMRemote::updateCover(FXImage * cover) {
  if (cover==NULL) {
    cover_label->setImage(img_default);
    }
  else {
    cover_label->setImage(cover);
    }
  }


void GMRemote::display(const GMTrack & track){
  title_label->setText(track.title);
  title_label->setJustify(JUSTIFY_LEFT);
//  title_label->setNumColumns(track.title.length());
  artistalbum_label->setText("by " + track.artist + " from " + track.album);
  artistalbum_label->show();
/*
  if (cover)
    cover_label->setIcon(cover);
  else
    cover_label->setIcon(icon_default);
*/
  recalc();

 // fxmessage("w: %d\n",getDefaultWidth());
  resize(FXMAX(300,getDefaultWidth()),getDefaultHeight());
  layout();

  //position(0,0,800,height);
  }

void GMRemote::reset(){
  title_label->setText("Goggles Music Manager");
  title_label->setJustify(JUSTIFY_CENTER_X);
  title_label->setLayoutHints(LAYOUT_CENTER_Y|LAYOUT_FILL_X);
  artistalbum_label->setText(FXString::null);
  artistalbum_label->hide();
  time_label->setText("--:--");
  recalc();
  resize(FXMAX(300,getDefaultWidth()),getDefaultHeight());
  layout();
  }

void GMRemote::elapsed_time(FXint hours,FXint minutes,FXint seconds,FXint,FXbool playing){
  if (playing) {
    if (hours>0)
      time_label->setText(GMStringFormat("%d:%.2d:%.2d",hours,minutes,seconds));
    else
      time_label->setText(GMStringFormat("%.2d:%.2d",minutes,seconds));
    }
  else {
    time_label->setText("--:--");
    }
  }

void GMRemote::update_volume_display(FXint level) {
  if (level<=0)
    volumebutton->setIcon(icon_volume_muted);
  else if (level<=33)
    volumebutton->setIcon(icon_volume_low);
  else if (level<=66)
    volumebutton->setIcon(icon_volume_medium);
  else
    volumebutton->setIcon(icon_volume_high);

  volumeslider->setValue(level);
  }


// Create and show window
void GMRemote::create(){
  FXMainWindow::create();
  FXint x = getApp()->reg().readIntEntry("window","remote-x",getX());
  FXint y = getApp()->reg().readIntEntry("window","remote-y",getY());
  //move(x,y);
  position(x,y,FXMAX(300,getDefaultWidth()),getDefaultHeight());
  gm_set_application_icon(this);
  show();
  }

bool GMRemote::doesOverrideRedirect() const { return FALSE; }


long GMRemote::onCmdVolume(FXObject*,FXSelector,void*ptr){
  FXint level = (FXint)(FXival)ptr;
  GMPlayerManager::instance()->volume(level);
  GMPlayerManager::instance()->getMainWindow()->update_volume_display(level);
  update_volume_display(level);
  return 1;
  }

long GMRemote::onCmdVolumeButton(FXObject*,FXSelector sel,void*ptr){
  volumeslider->handle(this,FXSEL(FXSELTYPE(sel),0),ptr);
  return 1;
  }

long GMRemote::onUpdVolumeButton(FXObject*sender,FXSelector,void*){
  if (GMPlayerManager::instance()->audio_device_opened())
    sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
  else
    sender->handle(this,FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
  return 1;
  }


#endif

