/*
 * TagMenuクラス
 *
 *--------------------------------------------------------------------- */
var TagMenu = Class.create();

/*
 * Singleton
 */
TagMenu.instance = null;

TagMenu.getInstance = function() {
  var instance = TagMenu.instance;

  if (instance == null) {
    instance = TagMenu.instance = new TagMenu();
  }

  return instance;
}

TagMenu.LOCATION_MARGIN = -11;

TagMenu.prototype = {

  /*
   * Instance properties
   *
   *--------------------------------------------------------------------- */
  tag: null,

  /*
   * Constructor
   *
   *--------------------------------------------------------------------- */
  initialize: function() {

    /*
     * タグメニューの要素を取得する。
     */
    var tagMenu = $('tag_menu');
    var header = tagMenu.getElementsByClassName('header')[0];
    var closer = header.getElementsByTagName('a')[0];
    var content = tagMenu.getElementsByClassName('content')[0];
    var tagRemover = content.getElementsByClassName('tag_remover')[0];
    var linkerAdder = content.getElementsByClassName('linker_adder')[0];
    var linkerRemover = content.getElementsByClassName('linker_remover')[0];

    /*
     * タグメニューのドラッグを有効にする。
     */
    var width = tagMenu.getWidth();
    var height = tagMenu.getHeight();

    new Draggable(tagMenu, {
      handle: header,

      starteffect: function(dragElement) {
        dragElement.setStyle({opacity: 0.5, zIndex: 2000});
      },

      snap: function(x, y) {
        var tagDeployer = $('tag_deployer');
        var xLimit = tagDeployer.getWidth() - 3;
        var yLimit = tagDeployer.getHeight() - 3;

        x = (x < 0) ? 0 : (x + width > xLimit ? xLimit - width : x);
        y = (y < 0) ? 0 : (y + height > yLimit ? yLimit - height : y);

        return [x, y];
      }
    });

    /*
     * タグメニューのヘッダ内のアンカータグに対して,
     * タグメニューを閉じるイベントを付与する。
     */
    closer.observe('click', function(event) {
      TagMenu.getInstance().hide();
      Event.stop(event);
    });

    /*
     * "タグ削除"イベントを付与する。
     */
    tagRemover.observe('click', function(event) {
      ProgressManager.getInstance().removeTag(this.tag);
      Event.stop(event);
    }.bind(this));

    /*
     * リンカ追加要素のドラッグを有効にする。
     */
    new Draggable(linkerAdder, {
      handler: linkerAdder,
      revert: true
    });

    /*
     * リンカ削除要素のドラッグを有効にする。
     */
    new Draggable(linkerRemover, {
      handler: linkerRemover,
      revert: true
    });

  },

  /*
   * show
   *
   *--------------------------------------------------------------------- */
  show: function(tag) {

    /*
     * 処理に必要な要素を取得する。
     */
    var tagMenu = $('tag_menu');
    var title = tagMenu.getElementsByClassName('header')[0].getElementsByTagName('span')[0];

    /*
     * タイトルにタグ名を表示し, タグメニューを表示する。
     */
    title.innerHTML = 'メニュー(' + tag.getTagName() + ')';
    tagMenu.style.display = 'block';

    /*
     * 処理対象タグを保持する。
     */
    this.tag = tag;

  },

  /*
   * hide
   *
   *--------------------------------------------------------------------- */
  hide: function() {
    $('tag_menu').style.display = 'none';
  },

  /*
   * locate
   *
   *--------------------------------------------------------------------- */
  locate: function(x, y) {

    /*
     * タグ配置要素のサイズを取得する。
     */
    var tagDeployer = $('tag_deployer');
    var tagDeployerWidth = tagDeployer.getWidth() - 3;
    var tagDeployerHeight = tagDeployer.getHeight() - 3;

    /*
     * タグメニューの表示位置を求める。
     */
    var offset = Position.cumulativeOffset(tagDeployer);
    var realOffset = Position.realOffset(tagDeployer);
    var locationMargin = TagMenu.LOCATION_MARGIN;
    var left = x - offset[0] + realOffset[0] + locationMargin;
    var top = y - offset[1] + realOffset[1] + locationMargin;

    /*
     * タグ配置要素からタグメニューがはみださないように,
     * タグメニューの表示位置を調整する。
     */
    var tagMenu = $('tag_menu');
    var width = tagMenu.getWidth();
    var height = tagMenu.getHeight();

    if (left < 0) {
      left = 0;
    } else if (left + width > tagDeployerWidth) {
      left = tagDeployerWidth - width;
    }

    if (top < 0) {
      top = 0;
    } else if (top + height > tagDeployerHeight) {
      top = tagDeployerHeight - height;
    }

    /*
     * タグメニューの表示位置を設定する。
     */
    tagMenu.setStyle({left: left + 'px', top: top + 'px'});

  },

  /*
   * locateAndShow
   *
   *--------------------------------------------------------------------- */
  locateAndShow: function(x, y, tag) {
    this.locate(x, y);
    this.show(tag);
  },

  /*
   * getTag
   *
   *--------------------------------------------------------------------- */
  getTag: function() {
    return this.tag;
  }

};

