# session-english.rb: Session library for English.
# $Id: session-english.rb,v 1.2 2005/03/07 07:51:32 komatsu Exp $
#
# Copyright (C) 2005 Hiroyuki Komatsu <komatsu@taiyaki.org>
#     All rights reserved.
#     This is free software with ABSOLUTELY NO WARRANTY.
#
# You can redistribute it and/or modify it under the terms of 
# the GNU General Public License version 2.

require 'prime/session'
require 'prime/composer'

require 'prime/engine/engine-english'
require 'prime/engine/engine-userdict2-en'
require 'prime/engine/engine-personaldict'
require 'prime/engine/engine-alphabet'
require 'prime/engine/engine-number'

class PrimeSessionEnglish < PrimeSession
  include PrimeComposer

  def initialize ()
    name = "English"
    engine_classes = [
      :PrimeEngineEnglish,
      :PrimeEngineUserdict2English,
      :PrimeEnginePersonalDict,
      :PrimeEngineAlphabet,
      :PrimeEngineNumber,
    ]
    super(name, engine_classes)
    @language = "English"
  end

  def set_conversions (conversions)
    @conversions = conversions
  end

  def set_selection (index_no)
    @conversions.set_conversion_index(index_no)
    return @conversions[index_no]
  end
  def get_selection ()
    return @conversions.get_conversion()
  end

  def set_context (context)
    @context = context
  end
  def get_context ()
    return @context
  end

  ##
  ## Context methods
  ##
  def context_reset ()
    set_context("")
  end

  def context_set_previous_segment (segment)
    context_set_previous_word( segment.get_base() )
  end

  def context_set_previous_word (word)
    set_context(word)
  end


  ##
  ## Conversion methods
  ##

  ## This returns a PrimeConversionList.
  def conv_convert (method = nil)
    conversions_compact = convert_compact()
    ## FIXME: Delete the magic number.
    ## FIXME: (2004-12-22) <Hiro>
    conversions_compact.add_score( 50000 )
    conversions_prefix = convert_prefix()

    conversions = PrimeConversionList::merge( conversions_compact,
                                              conversions_prefix )
    set_conversions(conversions)
    return conversions
  end

  def conv_predict (method = nil)
    conversions = convert_compact()
    set_conversions(conversions)
    return conversions
  end

  def conv_select (index)
    conversion = set_selection(index)
    return conversion
  end

  def conv_commit ()
    conversion = get_selection()

    ## Commit the current conversion
    conversion.segments.each { | segment |
      learn_segment( segment, get_context() )

      context_reset()
      context_set_previous_segment(segment)
    }
    commited_string = conversion.get_literal()

    ## Reset the conversion.
    edit_erase()

    return commited_string
  end

  def learn_segment (segment, context)
    base         = segment.get_base()
    base_reading = segment.get_base_reading()
    pos          = segment.get_pos()
    adjunct      = segment.get_adjunct()
    rest         = ""

    @engines.command(:learn_word,
                     base_reading, base, pos, context, adjunct, rest)
  end

  def _adhoc_wordlist_to_conversionlist (wordlist)
    conversion_list = []
    wordlist.length.times { | index |
      word = wordlist[index]
      reading = word.to_text_pron()

      segment = PrimeSegment.new(reading)
      segment.set_candidates(wordlist, index)

      conversion_list.push( PrimeConversion.new( [segment], word.score ) )
    }
    return PrimeConversionList.new(conversion_list)
  end

  private
  ## This is a wrapper for convert_*.  This converts query to
  ## a PrimeConversionList insted of PrimeWordList and returns it.
  def convert (query)
    query.input.uniq!()
    words_list = @engines.command(:search, query)
    wordlist = PrimeWordList::merge(words_list)

    PrimeWordList::attach_prefix(@context, wordlist)
    return _adhoc_wordlist_to_conversionlist( wordlist )
  end
  private :convert

  def convert_compact ()
    conversion = convert_prefix().first()

    ## If the result of search_prefix is empty, this method stops the following
    ## search_japanese_uniclause for the quickness.
    if conversion.nil?() then
      return PrimeConversionList.new()
    end

    ## Predict a next segment of the conversion.
    next_segment = predict_next_segment( conversion )
    if next_segment.nil? then
      return PrimeConversionList.new( [conversion] )
    end

    conversion2 = conversion.dup()
    conversion2.segment_insert(next_segment)
    return PrimeConversionList.new( [conversion, conversion2] )
  end

  def convert_prefix ()
    # ¡Ö¤è¢ªÍ½Â¬¡×
    context  = get_context()
    expansion = @composer.edit_get_expansion()
    query = PrimeQuery.new(expansion, nil, :prefix, context)
    return convert(query)
  end

  ## This predicts candidate words as a next word for the specified conversion
  ## data.  For example when the specified conversion means "looking",
  ## one of the results would contain "forward".
  def predict_next_segment (conversion)
    if conversion.nil? then
      return nil
    end

    ## The current context is just the previous word.
    context = conversion.get_literal()

    query = PrimeQuery.new([""], nil, :context, context)
    next_words = search(query)
    if next_words.empty? then
      return nil
    end

    ## Create a PrimeSegment from the first value of a PrimeWord.
    next_words = next_words[0,1]

    next_word  = next_words.first
    next_word.prefix = Prime::get_prefix(context, next_word.literal)

    reading      = next_word.to_text_pron()
    base_reading = ""
    pos          = nil
    adjunct      = ""
    pos_adjunct  = nil

    next_segment = PrimeSegment.new(reading, base_reading, pos,
                                    adjunct, pos_adjunct, context)
    next_segment.set_candidates(next_words, 0)
    return next_segment
  end
  private :predict_next_segment

  #### ------------------------------------------------------------
  ## FIXME: revise the following mehods.
  ## FIXME: (2005-01-31) <Hiroyuki Komatsu>
  def search (query)
    query.input.uniq!()
    words_list = @engines.command(:search, query)
    return PrimeWordList::merge(words_list)
  end
end
  
