#!/usr/bin/ruby

require "gtk"

module Gtk
  ######################################################################
  # Gtk::EntryTable: extend Gtk Table widget to include some entry     #
  #             convenience functions                                  #
  #                                                                    #
  # Notes:                                                             #
  # - the default packing width for all of these calls is 2 cells      #
  ######################################################################
  class EntryTable < Gtk::Table
    attr_accessor :entries, :hspace, :vspace

    def initialize(*args)
      super(*args)
      @entries = Hash.new
      @hspace, @vspace = 0, 2
      set_col_spacings(5)
    end

    # add_separator - add a horizontal separator at x, y
    def add_separator(x, y, w = 2, h = 2)
      sep = Gtk::HSeparator.new
      attach(sep, x, x + w, y, y + h,
             Gtk::FILL | Gtk::EXPAND, 0, @hspace, @vspace)
      sep.show
    end

    # add_entry - add a text label and entry at x,y
    def add_entry(key, label, active, x, y, w = 2, h = 1)
      lw = Gtk::Label::new(label + ":")
      lw.set_alignment(1.0, 0.5)
      attach(lw, x, x + w / 2, y, y + h,
             Gtk::FILL, 0, @hspace, @vspace)
      lw.show

      @entries[key] = Gtk::Entry.new()
      @entries[key].set_editable(active)

      if block_given?
        @entries[key].signal_connect("changed") { |entry| yield key }
      end

      attach(@entries[key], x + 1, x + 2, y, y + 1,
             Gtk::FILL | Gtk::EXPAND, 0, @hspace, @vspace)
      @entries[key].show
    end

    # add_buttonbar - add an array of buttons at x,y
    def add_buttonbar(btns, x, y, w = 2, h = 1)
      hbox = Gtk::HBox.new(false, 2)

      btns.each { |vals|
        btn = Gtk::Button.new(vals[1])

        if block_given?
          btn.signal_connect("clicked") { |b| yield vals[0] }
        end

        hbox.pack_start(btn, true, true, 0)
        btn.show
      }

      attach(hbox, x, x + w, y, y + h,
             Gtk::FILL | Gtk::EXPAND, 0, @hspace, @vspace)
      hbox.show
    end
  end
end

module TrackUPS
  ######################################################################
  # TrackUPS::GtkInterface: GTK+ interface to TrackUPS                 #
  #                                                                    #
  # Notes:                                                             #
  # - Quit button uses exit in it's callback, so clicking this button  #
  #   will exit the program, regardless of the number of instances of  #
  #   windows                                                          #
  ######################################################################
  class GtkInterface
    attr_accessor :version, :win, :table, :results

    def initialize(tracking_number = "")
      @version = "0.0.3"

      # initialize window
      @win = Gtk::Window::new(Gtk::WINDOW_TOPLEVEL)
      @win.signal_connect("destroy") { exit }
      @win.signal_connect("delete_event") { exit }
      @win.set_title("GTK TrackUPS #{@version}")
      @win.border_width(5)

      # initialize top-level table
      @table = Gtk::EntryTable.new(2, 2, false)
      @table.show

      # initialize result frame
      frame = Gtk::Frame.new("Tracking Results")

      # initialize result table
      @results = Gtk::EntryTable.new(2, 2, false)
      @results.border_width(2)
      @results.show

      y = 0
      table.add_entry("track", "Tracking Number", true, 0, y += 1)
      table.entries["track"].set_text(tracking_number)
       
      # configure result frame and entries
      [["date",   "Date/Time",        false],
       ["loc",    "Location",         false], 
       ["status", "Status",           false],
       ["drop",   "Dropoff Location", false],
       ["sign",   "Signed For By",    false],
      ].each { |vals|
        if vals[0] =~ /^-/
          @results.add_separator(0, y += 1)
        else
          @results.add_entry(vals[0], vals[1], vals[2], 0, y += 1)
        end
      }
      
      # show result frame
      @table.attach(frame, 0, 2, y, y + 1,
                    Gtk::FILL | Gtk::EXPAND, Gtk::FILL | Gtk::EXPAND,
                    @table.hspace, @table.vspace)
      frame.show

      # add options button bar
      bar = [
        ["track", "Track"],
        ["save",  "Save Results"],
        ["quit",  "Quit"],
      ];
      @table.add_buttonbar(bar, 0, y += 1) { |key| clicked key }

      frame.add(@results)
      @results.show

      # add top-level table to window
      @win.add(@table)
      @win.show
    end

    # clicked - handle a clicked button from a buttonbar
    def clicked(label)
      case label
      when "track"
        track_request
      when "save"
        save_results
      when "quit"
        exit
      end
    end

    ####################
    # button callbacks #
    ####################
    def track_request
      num = @table.entries['track'].get_text
      $stderr.print "track #{num}\n"
      
      @results.entries.each { |key, val| val.set_text(num.to_s) }
    end

    def save_results
      num = @table.entries['track'].get_text

      # create file-selection dialog
      fs = Gtk::FileSelection.new("Save Tracking Results")
      fs.set_filename("results-#{num}.txt")

      # connect signals to ok and cancel buttons
      fs.ok_button.signal_connect("clicked") {
        confirmed_save_results(fs.get_filename)
        fs.destroy
      }
      fs.cancel_button.signal_connect("clicked") { fs.destroy }

      # show file-selection dialog
      fs.show
    end

    def confirmed_save_results(path)
      File.open(path, "w") { |f|
        f.print "HELLO JOSEPH\n"

        @results.entries.each { |key, val|
          f.print "#{key} => \"#{val.get_text}\"\n"
        }
      }
    end
  end
end


########################################################################
# If we're being called as a script, then treat the arguments on the   #
# command-line as tracking numbers and open a tracking window for each #
# one.                                                                 #
########################################################################

if $0 == __FILE__ 
  ARGV.push "" if ARGV.length == 0

  ARGV.each { |a| TrackUPS::GtkInterface.new(a) }

  Gtk::main
end

