#!/usr/bin/env ruby
# $Id: rwmuim,v 1.2 2005/10/20 15:29:46 masahino Exp $

require 'uim'
require 'dockapp'
require 'iconv'
require 'optparse'

$KCODE='e'

$uim_im_switcher="uim-im-switcher-gtk"
$uim_pref="uim-pref-gtk"
$uim_dict="uim-dict-gtk"
$version="0.2.1"


class Iconv
  def self.toeuc (charset, str)
    return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # us-ascii
    begin
      return Iconv.conv("euc-jp", charset, str)
    rescue Iconv::IllegalSequence
      return str
    end
    raise 'unable to convert to EUC-JP'
  end
end

class UIMProp
  def initialize(str)
    
  end
end

class WmUIMHelper
  def initialize(argv)
    check_args(argv)
    @uim_helper = UIM::Helper.new
    @uim_helper.init_client
    @uim_helper.send_message("im_list_get\n");
    @uim_helper.get_prop_list

    @dockapp = DockApp.new("WMUIM")
    @dockapp.openwindow
    @label = DockApp::Item.new(55, 16)
    @description = DockApp::Item.new(55, 16)
    @imname = DockApp::Text.new("", 6, 1, 0)
    @input = DockApp::Item.new(14, 14)

    @menu_popup = DockApp::PopUp.new(200, 200)
    @im_popup = DockApp::PopUp.new(100, 100)

    @dockapp.add( 0,  0, @label)
    @dockapp.add( 0, 20, @description)
    @dockapp.add(15, 40, @imname)
    @dockapp.add( 0, 40, @input)
    @dockapp.add( 0,  0, @menu_popup)
    @dockapp.add( 0,  0, @im_popup)

    @prop_list = Array.new
    @input_list = Array.new
    @im_list = Array.new

    @menu_popup.add_item("preference\ndictonary\nIM switch")

    set_timer
    set_button_callback
  end

  def set_button_callback
    @label.signal_connect("button_press_event") do |event|
      if event.button == 1
      pos = 0
      @prop_list.each do |p|
        list = p.split("\t")
        text = list[1]
        pos += text.length*6
        if event.x < pos
          @uim_helper.send_message("prop_activate\n"+list[4]+"\n")
          break
        end
      end
      end
    end
    
    @description.signal_connect("button_press_event") do |event|
      if event.button == 1
      for i in 0..@prop_list.size-1
        if @prop_list[i].split("\t")[5] == "*"
          n = i+1
          if n > @prop_list.size-1
            n = 0
          end
          @uim_helper.send_message("prop_activate\n"+@prop_list[n].split("\t")[4]+"\n")
          break
        end
      end
end
    end
    
    @imname.signal_connect("button_press_event") do |event|
      if event.button == 1
        system($uim_im_switcher)
      elsif event.button == 2
#        @im_popup.show(0, 0)
        @im_popup.popup() do |n|
          if n != nil
            im = @im_list[n].split("\t")[0]
            self.im_change(im)
          end
        end
      end
    end

    @input.signal_connect("button_press_event") do |event|
      if event.button == 1
      for i in 0..@input_list.size-1
        if @input_list[i].split("\t")[5] == "*"
          n = i+1
          if n > @input_list.size-1
            n = 0
          end
          @uim_helper.send_message("prop_activate\n"+@input_list[n].split("\t")[4]+"\n")
          break
        end
      end
end
    end

=begin
    @dockapp.signal_connect("button_release_event") do |event|
      if event.button == 3
        @popup.hide()
        # x Βϒϒʒ
        minx = @old_x - (@popup.width)/2
        maxx = @old_x + (@popup.width)/2
        if event.x > minx and event.x < maxx
          if event.y - @old_y <= 0
          elsif event.y - @old_y < 21
            fork do
              exec($uim_pref)
            end
          elsif event.y - @old_y < 42
            fork do
              exec($uim_dict)
            end
          elsif event.y - @old_y < 64
            fork do
              exec($uim_im_swither)
            end
          end
        end
      end
    end
=end
    @dockapp.signal_connect("button_press_event") do |event|
      if event.button == 3
        @menu_popup.popup() do |n|
          if n != nil
            if n == 0
              fork do
                exec($uim_pref)
                exit
              end
            elsif n == 1
              fork do
                exec($uim_dict)
                exit
              end
            elsif n == 2
              fork do
                exec($uim_im_switcher)
              end
            end
          end
        end
      end

#        @popup.show(0, 0)
#        @old_x = event.x
#        @old_y = event.y
#      end
    end

  end

  def set_timer
    label_timer = DockApp::Timer.new(100) do 
      if @uim_helper.readable
        @uim_helper.read_proc
        loop do
          str =  @uim_helper.get_message
          if str != nil
            message_array = str.split("\n")
            check_message(message_array)
          else
            break
          end
        end
      end
    end
    im_list_timer = DockApp::Timer.new(3000) do
      if @uim_helper.writable
        @uim_helper.send_message("im_list_get\n")
      end
    end
    label_timer.start
#    im_list_timer.start
  end


  def im_change(im)
    @uim_helper.send_message("im_change_whole_desktop\n"+im+"\n")
    @uim_helper.send_message("im_list_get\n")
  end

  def check_im_list
    @uim_helper.send_message("im_list_get\n")
  end
  
  def set_label(prop_list, update)
    p update if $DEBUG
    @label.clear
    x = 2
    for i in 0..prop_list.size-1
      text = prop_list[i]['label']
      if prop_list[i]['label'] == update['label']
        @label.draw_string(x, 12, text)
        @label.set_tip(prop_list[i]['menutooltip'])
        @description.clear
        @description.draw_string(2, 12, prop_list[i]['menulabel'][0..8])
        @description.set_tip(prop_list[i]['menutooltip'])
      else
        @label.draw_string(x, 12, text, "#000049244103")
      end
      x += text.length*6
    end
  end


  def set_input(label, description, tooltip)
    @input.clear
    @input.draw_string(1, 11, label)
    @input.set_tip(tooltip)
  end

  def parse_message(message_array)
    charset = message_array.shift
    dummy, charset = charset.split("=")
    return charset, message_array
  end    

  def im_list_update(message_array)
    charset, message_array = parse_message(message_array)
    @im_list = message_array
    @im_list.each do |im|
      if im.split("\t")[3] =~ %r|selected|
          @imname.set_text(im.split("\t")[0])
        @imname.set_tip(im.split("\t")[2])
        break
      end
    end
    menu_str = ""
    @im_list.each do |im|
      data = im.split("\t")
      menu_str += data[0]+"\n"
    end
    menu_str.chomp!
    @im_popup.add_item(menu_str)
  end

  def prop_label_update(message_array)
    charset, message_array = parse_message(message_array)
    label = message_array.shift
    label = Iconv.toeuc(charset, label)
    update = Hash.new
    update['label'], update['buttontooltip'] = label.split("\t")
    set_label(@prop_list, update)

  end

  def prop_list_update(message_array)
    charset, message_array = parse_message(message_array)
    branch = message_array.shift
    branch = Iconv.toeuc(charset, branch)
    update = Hash.new
    dummy, update['label'], update['buttontooltip'] = branch.split("\t")
    message_array.map! {|str| str = Iconv.toeuc(charset, str)}
    @prop_list = Array.new
    while message_array
      if message_array[0] =~ %r|^branch| or message_array.size == 0
          break
      end
      prop = Hash.new
      dummy, prop['label'], prop['menulabel'], prop['menutooltip'], prop['menucommand'], prop['flag'] =
        message_array.shift.split("\t")
      @prop_list.push(prop)
    end

    set_label(@prop_list, update)
    
    if message_array.size == 0
      return
    end
    branch = message_array.shift
    dummy, label, description = branch.split("\t")
    #   message_array.map! {|str| str = Iconv.conv("euc-jp", charset, str)}
    @input_list = message_array
    while message_array
      d1, d2, d3, d4 = message_array[0].split("\t")
      if d2 == label
        tooltip = d4
        break
      end
    end
    self.set_input(label, description, tooltip)
  end

  def check_message(message_array)
    puts message_array[0] if $DEBUG
    if message_array[0] == "prop_label_update"
      prop_label_update(message_array[1..-1])
    elsif message_array[0] == "prop_list_update"
      prop_list_update(message_array[1..-1])
      check_im_list
    elsif message_array[0] == "prop_activate"
      puts "prop_activate" if $DEBUG
    elsif message_array[0] == "im_list"
      im_list_update(message_array[1..-1])
    elsif message_array[0] == "focus_out"
      # not implement
    elsif message_array[0] == "focus_in"
      # not implement
    elsif message_array[0] == "im_list_get"
      puts "im_list_get" if $DEBUG
    else
      puts "not yet implement" if $DEBUG
      puts message_array[0] if $DEBUG
    end
  end

  def start
    @dockapp.start
  end

  def show_version
    puts $version
    exit
  end

  def check_args(argv)
    opt = OptionParser.new
    opt.on('-v') {|v| show_version }
    opt.parse!(argv)
  end
end

wmuim = WmUIMHelper.new(ARGV)
wmuim.start
