#!/usr/bin/env ruby

# recgtk.rb

# $Id: recgtk.rb,v 1.3 2002/05/13 23:26:37 kenji Exp $

# 2002/4/30  Takuro Ashie <ashie@homa.ne.jp>
# Copyright (C) 2002 Takuro Ashie <ashie@homa.ne.jp>
# This is free software with ABSOLUTELY NO WARRANTY.

# 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


# get Video Recording Directory
if FileTest::symlink?( __FILE__ ) then
  bin_path = File::dirname(File::readlink(File::expand_path( __FILE__ )))
else
  bin_path = File::dirname(File::expand_path( __FILE__ ))
end
VideoRecordingDir = File::dirname(bin_path)
VideoRecordingLibDir  = VideoRecordingDir + "/lib"
VideoRecordingVarDir  = VideoRecordingDir + "/var"
VideoRecordingConfDir = VideoRecordingDir + "/conf"
VideoRecordingGtkLibDir  = VideoRecordingDir + "/lib/gtk"

$: << VideoRecordingLibDir
$: << VideoRecordingGtkLibDir


require 'gtk'
require 'option_dialog'
require 'program_entry'
require 'program_clist'

require 'program_item'
require 'program_admin'


# set to IEPG mode if command line argument is given.
if ARGV[0]
  IEPG_mode = true
else
  IEPG_mode = false
end


# play back command
def playMovie(aFilename)
  if filename && File::exist?(aFilename) then
    system("mplayer #{filename} &")
  end
end



###############################################################################
#
#   Main Window Widget
#
###############################################################################
class MainWindow < Gtk::Window
  include Gtk

  #
  # initialize()
  #
  def initialize()
    super(WINDOW_TOPLEVEL)

    @prog_admin  = ProgramAdmin::new

    ### initialize
    @clist_prog    = nil   # Gtk::ProgramCList
    @prog_entry    = nil   # Gtk::ProgramEntry

    @add_button    = nil   # Gtk::Button
    @change_button = nil   # Gtk::Button
    @del_button    = nil   # Gtk::Button
    @play_button   = nil   # Gtk::Button

    @selected_item = nil   # ProgramItem

    ### set window properties
    set_title("録画予約")
    set_default_size(500, 300)
    signal_connect('destroy') do
      exit
    end

    createChildren
  end


  #
  # setProgram() :
  #    set values to the entries.
  #
  # list : Array which contain ProgramItem
  #
  def setProgram(aProgram)
    @prog_entry.setProgram(aProgram)
  end


  #
  # setIepg() :
  #    set iEPG data to the entries.
  #
  # list : Array which contain ProgramItem.
  #
  def setIepg(aProgram)
    setProgram(aProgram)
  end


  #
  # setProgramList() :
  #    Set program list to the CList widget.
  #    If list is already exist, it will be cleared first.
  #
  # list : Array which contain ProgramItem
  #
  def setProgramList(aList)
    @clist_prog.setList(aList)
    @selected_item = nil
    @change_button.set_sensitive(false)
    @del_button.set_sensitive(false)
    @play_button.set_sensitive(false)
  end


 private

  ####################################
  #   Method for creating GUI parts
  ####################################

  #
  # createMainMenu() :
  #
  def createMainMenu()
    menubar = MenuBar::new

    filemitem = MenuItem::new('ファイル')
    filemitem.show

    filemenu = Menu::new
    item = MenuItem::new('録画リスト取得')
    item.show
    filemenu.add item
    item.signal_connect('activate') do
      begin
        @prog_admin.loadList
        setProgramList(@prog_admin.program_list)
      rescue
        printf "予約リストの読み込みに失敗しました\n"
      end
    end

    item = MenuItem::new('終了')
    item.show
    filemenu.add item
    item.signal_connect('activate') do
      exit
    end

    filemitem.set_submenu filemenu
    menubar.append filemitem

    return menubar
  end


  #
  # createButtonArea() :
  #
  def createButtonArea()
    hbox = HBox::new(false, 0)
    hbox.show

    ### Add Button
    @add_button = Button::new("予約を登録")
    hbox.pack_start(@add_button)
    @add_button.show

    @add_button.signal_connect('clicked') do
      item = @prog_entry.getProgram

      if !item.valid? then
        ErrorDialog::new("値が不正です").popup
        break
      end

      if @prog_admin.doubleBooking?(item) then
        ErrorDialog::new("時間帯が重複する予約が存在します").popup
        break
      end

      yes = QuestionDialog::new("本当に登録しますか?").popup
      if !yes then
        break
      end

      list = @prog_admin << item
      if list then
        setProgramList(list)
      end
    end

    ### Change Button
    @change_button = Button::new("予約を変更")
    hbox.pack_start(@change_button)
    # @change_button.show
    @change_button.set_sensitive(false)

    @change_button.signal_connect('clicked') do
      item = @prog_entry.getProgram

      if !item.valid? then
        ErrorDialog::new("入力データに不正な値が含まれます．").popup
        break
      end

      if !@prog_admin.include? (@selected_item) then
        ErrorDialog::new("選択データと一致する予約が存在しません．").popup
        break
      end

      if @prog_admin.doubleBooking? (item, true) then
        ErrorDialog::new("時間帯が重複する予約が存在します．").popup
        break
      end

      yes = QuestionDialog::new("本当に登録しますか?").popup
      if yes != QuestionDialog::YES then
        break
      end

      list = @prog_admin << item
      if list then
        setProgramList(list)
      end
    end

    ### Delete Button
    @del_button = Button::new("予約を削除")
    hbox.pack_start (@del_button)
    @del_button.show
    @del_button.set_sensitive (false)

    @del_button.signal_connect ('clicked') do
      retval = QuestionDialog::new("本当に削除しますか?").popup

      if retval == QuestionDialog::YES then
        item = @prog_entry.getProgram
        list = @prog_admin.delete_program item
        if list then
          setProgramList(list)
	end
      end
    end

    ### Play Button
    @play_button = Button::new("再生")

    @play_button.signal_connect('clicked') do
      if @selected_item then
        playMovie(@selected_item.filename)
      end
    end

    hbox.pack_start(@play_button)
    @play_button.show
    @play_button.set_sensitive(false)

    return hbox
  end


  #
  # createChildren() :
  #    Create all child widget.
  #
  def createChildren()
    main_vbox = VBox::new(false, 0)
    add(main_vbox)
    main_vbox.show

    ### Menu
    main_menu = createMainMenu
    main_menu.show
    main_vbox.pack_start(main_menu, false, false, 0)

    ### Main contents
    vbox = VBox::new(false, 5)
    main_vbox.pack_start(vbox)
    vbox.show

    ### Clock
    @clock = Label::new(Time::now.strftime ("%Y年%m月%d日 %H:%M:%S %Z"))
    vbox.pack_start(@clock, false, false, 1)
    @clock.show
    timeout_add(100) do
      @clock.set_text(Time::now.strftime("%Y年%m月%d日 %H:%M:%S %Z"))
      true
    end

    ### Reservation list view
    scrolled = ScrolledWindow::new
    scrolled.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
    vbox.pack_start (scrolled)
    scrolled.show

    @clist_prog = ProgramCList::new
    @clist_prog.set_usize(300, 200)
    scrolled.add(@clist_prog)
    @clist_prog.show

    @clist_prog.signal_connect('select_row') do |clist, row, col, event|
      item = clist.get_row_data(row)
      @prog_entry.setProgram(item)
      @selected_item = item
      @change_button.set_sensitive(true)
      @del_button.set_sensitive(true)
      if File::exist?(item.filename) then
        if item.obsolete? then
          @play_button.set_sensitive(true)
        else
          @play_button.set_sensitive(!item.now?)
        end
      else
        @play_button.set_sensitive(false)
      end
    end

    @clist_prog.signal_connect('unselect_row') do |clist, row, col, event|
      @selected_item = nil
      @change_button.set_sensitive(false)
      @del_button.set_sensitive(false)
      @play_button.set_sensitive(false)
    end

    ### Reservation entry area
    @prog_entry = ProgramEntry::new
    vbox.pack_start(@prog_entry)
    @prog_entry.show
    @prog_entry.setChannelItems(@prog_admin.channel_list)
    @prog_entry.setQualityItems(@prog_admin.quality_list)

    ### Buttons area
    button_area = createButtonArea
    vbox.pack_start(button_area, false, false, 0);
    button_area.show

    # Status Bar
    # statusbar = Statusbar::new
    # main_vbox.pack_start(statusbar, false, false, 0)
    # statusbar.show

    setProgramList(@prog_admin.program_list)
  end
end



###############################################################################
#
#   main
#
###############################################################################

gui = MainWindow::new
gui.show

if IEPG_mode then

  begin
    string = ""
    open(ARGV.last) do |file|
      string = file.read
    end
    iepg = IEPG::new (string)
    gui.setIepg(iepg)

  rescue
    ErrorDialog::new("iEPGデータの読み込みに失敗しました").popup
  end

end

Gtk.main
