/*******************************************************************************
*                         Goggles Music Manager                                *
********************************************************************************
*           Copyright (C) 2007-2011 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 "gmdefs.h"
#include <fxkeys.h>
#include "GMApp.h"
#include "GMList.h"
#include "GMTrackList.h"
#include "GMSourceView.h"
#include "GMTrackView.h"
#include "GMWindow.h"
#include "GMSource.h"
#include "GMDatabaseSource.h"
#include "GMStreamSource.h"
#include "GMPlayerManager.h"
#include "GMIconTheme.h"



FXDEFMAP(GMSourceView) GMSourceViewMap[]={
  FXMAPFUNC(SEL_COMMAND,GMSourceView::ID_SOURCE_LIST_HEADER,GMSourceView::onCmdSortSourceList),
  FXMAPFUNC(SEL_RIGHTBUTTONRELEASE,GMSourceView::ID_SOURCE_LIST,GMSourceView::onSourceContextMenu),
  FXMAPFUNC(SEL_COMMAND,GMSourceView::ID_SOURCE_LIST,GMSourceView::onCmdSourceSelected),
  FXMAPFUNC(SEL_DND_MOTION,GMSourceView::ID_SOURCE_LIST,GMSourceView::onDndSourceMotion),
  FXMAPFUNC(SEL_DND_DROP,GMSourceView::ID_SOURCE_LIST,GMSourceView::onDndSourceDrop),
  FXMAPFUNC(SEL_COMMAND,GMSourceView::ID_NEW_PLAYLIST,GMSourceView::onCmdNewPlayList),
  FXMAPFUNC(SEL_UPDATE,GMSourceView::ID_NEW_PLAYLIST,GMSourceView::onUpdNewPlayList),
  FXMAPFUNC(SEL_COMMAND,GMSourceView::ID_NEW_STATION,GMSourceView::onCmdNewStation),
  FXMAPFUNC(SEL_COMMAND,GMSourceView::ID_EXPORT,GMSourceView::onCmdExport),
  FXMAPFUNC(SEL_UPDATE,GMSourceView::ID_EXPORT,GMSourceView::onUpdExport),
  };

FXIMPLEMENT(GMSourceView,GMScrollFrame,GMSourceViewMap,ARRAYNUMBER(GMSourceViewMap))

GMSourceView::GMSourceView() : source(NULL) {
  }

GMSourceView::GMSourceView(FXComposite* p) : GMScrollFrame(p) , source(NULL) {
  sourcelistheader = new GMHeaderButton(this,tr("Sources\tPress to change sorting order\tPress to change sorting order"),NULL,this,ID_SOURCE_LIST_HEADER,LAYOUT_FILL_X|FRAME_THICK|FRAME_RAISED|JUSTIFY_LEFT);
  sourcelist       = new GMTreeList(this,this,ID_SOURCE_LIST,LAYOUT_FILL_X|LAYOUT_FILL_Y|TREELIST_BROWSESELECT);

  sourcelist->dropEnable();
  sourcelist->setSortFunc(source_list_sort);

  sourcelistheader->setArrowState(ARROW_DOWN);

  updateColors();
  }

GMSourceView::~GMSourceView(){
  }

void GMSourceView::updateColors() {
  sourcelist->setRowColor(GMPlayerManager::instance()->getPreferences().gui_row_color);
  }

void GMSourceView::updateSource(GMSource * src){
  FXTreeItem * item = sourcelist->getFirstItem();
  while(item) {
    if (item->getData()==src) {
      item->setText(tr(src->getName().text()));
      break;
      }
    item=item->getNext();
    }
  resort();
  }


void GMSourceView::setSource(GMSource * src,FXbool makecurrent/*=true*/){
  if (src!=source) {
    source=src;
    if (makecurrent) {
      FXTreeItem * item = sourcelist->getFirstItem();
      while(item) {
        if (item->getData()==src) {
          sourcelist->setCurrentItem(item,false);
          break;
          }
        item=item->getNext();
        }
      }
    GMPlayerManager::instance()->getTrackView()->setSource(source);
    }
  }


void GMSourceView::clear() {
  sourcelist->clearItems();
  }


void GMSourceView::refresh() {
  clear();
  listSources();
  }


void GMSourceView::init() {
  loadSettings("window");
  clear();
  listsources();


  FXString key = getApp()->reg().readStringEntry("window","source-list-current","");
  if (!key.empty()){
    FXTreeItem * item = sourcelist->getFirstItem();
    while(item) {
      GMSource * src = (GMSource*)item->getData();
      if (src->settingKey()==key) {
        sourcelist->setCurrentItem(item);
        break;
        }
      item=item->getNext();
      }
    }

  if (sourcelist->getCurrentItem()==NULL && sourcelist->getFirstItem())
    sourcelist->setCurrentItem(sourcelist->getFirstItem());

  source=(GMSource*)sourcelist->getItemData(sourcelist->getCurrentItem());
  GMPlayerManager::instance()->getTrackView()->init(source);
  }


void GMSourceView::resort() {
  sortSources();
  }


FXbool GMSourceView::listsources() {
  GMTreeItem * item=NULL;
  for (FXint i=0;i<GMPlayerManager::instance()->getNumSources();i++){
    GMSource * source = GMPlayerManager::instance()->getSource(i);
    switch(source->getType()){
      case SOURCE_DATABASE         : item = new GMTreeItem(tr(source->getName().text()),GMIconTheme::instance()->icon_source_library,GMIconTheme::instance()->icon_source_library,source); break;
      case SOURCE_DATABASE_PLAYLIST: item = new GMTreeItem(tr(source->getName().text()),GMIconTheme::instance()->icon_source_playlist,GMIconTheme::instance()->icon_source_playlist,source); break;
      case SOURCE_INTERNET_RADIO   : item = new GMTreeItem(tr(source->getName().text()),GMIconTheme::instance()->icon_source_internetradio,GMIconTheme::instance()->icon_source_internetradio,source); break;
      default                      : item = NULL; break;
      }
    if (item) {
      sourcelist->appendItem(NULL,item);
      }
    }
  sourcelist->sortItems();
  return true;
  }


FXbool GMSourceView::listSources() {
  listsources();
  setSource((GMSource*)sourcelist->getItemData(sourcelist->getCurrentItem()),false);
  return true;
  }


void GMSourceView::sortSources() const{
  sourcelist->sortItems();
  }


void GMSourceView::loadSettings(const FXString & key) {
  FXbool sort_reverse,shown;

  sort_reverse = getApp()->reg().readBoolEntry(key.text(),"source-list-sort-reverse",false);
  if (sort_reverse)
    sourcelist->setSortFunc(source_list_sort_reverse);
  else
    sourcelist->setSortFunc(source_list_sort);

  shown = getApp()->reg().readBoolEntry(key.text(),"source-list",true);
  if (shown)
    getParent()->show();
  else
    getParent()->hide();
  }


void GMSourceView::saveSettings(const FXString & key) const {
  getApp()->reg().writeBoolEntry(key.text(),"source-list-sort-reverse",sourcelist->getSortFunc()==source_list_sort_reverse);
  getApp()->reg().writeBoolEntry(key.text(),"source-list",getParent()->shown());
  }



void GMSourceView::saveView() const {
  saveSettings("window");
  if (source) {
    getApp()->reg().writeStringEntry("window","source-list-current",source->settingKey().text());
    }
  }


long GMSourceView::onCmdSourceSelected(FXObject*,FXSelector,void*){
  FXTreeItem * item = sourcelist->getCurrentItem();
  if (item) {
    setSource((GMSource*)item->getData(),false);
    }
  return 1;
  }


long GMSourceView::onCmdSortSourceList(FXObject*,FXSelector,void*){
  if (sourcelist->getSortFunc()==source_list_sort) {
    sourcelist->setSortFunc(source_list_sort_reverse);
    sourcelistheader->setArrowState(ARROW_UP);
    }
  else {
    sourcelist->setSortFunc(source_list_sort);
    sourcelistheader->setArrowState(ARROW_DOWN);
    }
  sortSources();
  return 1;
  }


long GMSourceView::onSourceContextMenu(FXObject*,FXSelector,void*ptr){
  FXEvent * event = reinterpret_cast<FXEvent*>(ptr);
  if (event->moved) return 0;
  GMTreeItem * item = dynamic_cast<GMTreeItem*>(sourcelist->getItemAt(event->win_x,event->win_y));
  GMMenuPane pane(this);
  if (item) {
    GMSource * source = (GMSource*)item->getData();
    if (source && source->source_context_menu(&pane)) {
      sourcelist->setCurrentItem(item);
      onCmdSourceSelected(NULL,0,NULL); // Simulate SEL_COMMAND
      }
    }
  else {
    new GMMenuCommand(&pane,tr("New Playlist…\t\tCreate a new playlist"),GMIconTheme::instance()->icon_playlist,this,ID_NEW_PLAYLIST);
    new GMMenuCommand(&pane,tr("Import Playlist…\t\tImport existing playlist"),GMIconTheme::instance()->icon_import,GMPlayerManager::instance()->getDatabaseSource(),GMDatabaseSource::ID_IMPORT_PLAYLIST);
    new GMMenuCommand(&pane,tr("New Radio Station…\t\tCreate a new playlist"),NULL,this,GMSourceView::ID_NEW_STATION);
    }
  pane.create();
  ewmh_change_window_type(&pane,WINDOWTYPE_POPUP_MENU);
  pane.popup(NULL,event->root_x,event->root_y);
  getApp()->runPopup(&pane);
  return 1;
  }


long GMSourceView::onDndSourceMotion(FXObject*,FXSelector,void*ptr){
  FXEvent * event = reinterpret_cast<FXEvent*>(ptr);
  GMTreeItem * item = dynamic_cast<GMTreeItem*>(sourcelist->getItemAt(event->win_x,event->win_y));
  if (item) {
    GMSource * source = reinterpret_cast<GMSource *>(item->getData());
    FXDragType*types;
    FXuint     ntypes;
    if (sourcelist->inquireDNDTypes(FROM_DRAGNDROP,types,ntypes)){
      if (source->dnd_source_accepts(types,ntypes)){
        sourcedrop=source;
        sourcelist->acceptDrop(DRAG_LINK);
        freeElms(types);
        return 1;
        }
      freeElms(types);
      }
    }
  sourcedrop=NULL;
  return 0;
  }



long GMSourceView::onDndSourceDrop(FXObject*sender,FXSelector,void*ptr){
  if (sourcedrop) {
    long code =  sourcedrop->handle(sender,FXSEL(SEL_DND_DROP,GMSource::ID_DROP),ptr);
    sourcedrop=NULL;
    return code;
    }
  return 0;
  }


long GMSourceView::onCmdNewPlayList(FXObject*sender,FXSelector,void*ptr){
  if (GMPlayerManager::instance()->getSource(0))
    return GMPlayerManager::instance()->getSource(0)->handle(sender,FXSEL(SEL_COMMAND,GMDatabaseSource::ID_NEW_PLAYLIST),ptr);
  return 0;
  }


long GMSourceView::onUpdNewPlayList(FXObject*sender,FXSelector,void*ptr){
  if (GMPlayerManager::instance()->getSource(0))
    return GMPlayerManager::instance()->getSource(0)->handle(sender,FXSEL(SEL_UPDATE,GMDatabaseSource::ID_NEW_PLAYLIST),ptr);
  return 0;
  }


long GMSourceView::onCmdNewStation(FXObject*sender,FXSelector,void*ptr){
  for (FXint i=0;i<GMPlayerManager::instance()->getNumSources();i++){
    GMSource * source = GMPlayerManager::instance()->getSource(i);
    if (source->getType()==SOURCE_INTERNET_RADIO)
      return source->handle(sender,FXSEL(SEL_COMMAND,GMStreamSource::ID_NEW_STATION),ptr);
    }
  return 0;
  }

long GMSourceView::onCmdExport(FXObject*sender,FXSelector,void*ptr){
  if (source)
    return source->handle(sender,FXSEL(SEL_COMMAND,GMSource::ID_EXPORT),ptr);
  return 0;
  }


long GMSourceView::onUpdExport(FXObject*sender,FXSelector,void*ptr){
  if (source)
    return source->handle(sender,FXSEL(SEL_UPDATE,GMSource::ID_EXPORT),ptr);
  return 0;
  }
