# array-agent.rb: This ArrayAgent class Managements an array and its index.
#                 Each instance of ArrayAgent synchronizes its index
#                 each other.
# $Id: array-agent.rb,v 1.2 2005/03/07 07:51:32 komatsu Exp $
#
# Copyright (C) 2004 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.
#

class ArrayAgent
  @@agents = {}

  def initialize (array = [], index = 0)
    open(array, index)
  end

  def open (array = [], index = 0)
    @array = array
    @index = index
    if @@agents.has_key?(@array.id) then
      @@agents[@array.id].push(self)
    else
      @@agents[@array.id] = [self]
    end
  end

  def close ()
    @@agents[@array.id].delete(self)
    @array = nil
    @index = nil
  end

  #### Array operations

  def get_array ()
    return @array
  end

  def get_length ()
    return @array.length
  end

  #### Index operations

  def get_index ()
    return @index
  end

  def set_index (index)
    if index < 0 or index > @array.length then
      return false
    else
      @index = index
      return true
    end
  end

  def go_next ()
    return set_index(@index + 1)
  end
  def go_previous ()
    return set_index(@index - 1)
  end
  def go_prev ()
    return set_index(@index - 1)
  end

  def go_first ()
    return set_index(0)
  end
  def go_last ()
    return set_index(get_length())
  end

  def is_first? ()
    return (@index == 0)
  end
  def is_last? ()
    return (@index == @array.length)
  end

  #### Item operations

  def get_item ()
    return get_item_at(@index)
  end
  def get_item_at (index)
    if is_last?() then
      return nil
    end
    return @array[index]
  end

  ## [ 0 1*2 3 ].delete_item() => [ 0 1*3 ]   (true)
  ## [*0 1 2 3 ].delete_item() => [*1 2 3 ]   (true)
  ## [ 0 1 2 3*].delete_item() => [ 0 1 2 3*] (false)
  def delete_item (length = 1)
    return delete_item_at(@index, length)
  end
  def delete_item_at (index, length = 1)
    if is_last?() then
      return false
    end

    @array.slice!(index, length)
    @@agents[@array.id].each { | agent |
      agent.delete_index(index, length)
    }
    return true
  end

  ## [ 0 1 2 3*].intert_item(4) => [ 0 1 2 3 4*]
  ## [ 0 1*2 3 ].intert_item(4) => [ 0 1 4*2 3 ]
  ## [*0 1 2 3 ].intert_item(4) => [ 4*0 1 2 3 ]
  def insert_item (item)
    insert_item_at(@index, item)
  end
  def insert_item_at (index, item)
    if is_last?() then
      @array.push(item)
    else
      @array[index,1] = [item, @array[index]]
    end
    @@agents[@array.id].each { | agent |
      agent.insert_index(index, 1)
    }
  end

  #### Index operations

  def delete_index (index, length)
    if @index > index + length then
      @index -= length
    elsif @index > index then
      @index = index
    end
  end

  def insert_index (index, length)
    if @index >= index then
      @index += length
    end
  end
end
