// -----------------------------------------------------------------------
// TINAMI Comike Map System Ver 2006.12.04
// (c) 2006 TINAMI. All rights reserved.
// control.js: 初期表示やマウスの入力を制御するクラス
// -----------------------------------------------------------------------
var Control = Class.create();
Control.prototype = {
  initialize: function (map_id)
  {
    this.MapID = map_id;  // マップを表示するdivのid

    // マウス関連
    this.from = new Object();  // マウスの移動開始位置
    this.to = new Object();    // マウスの移動終了位置
    this.isDrag = false;       // ドラッグ中ならTrue
    this.isClick = true;       // クリックならTrue

    // マップ
    this.mapCollection = new MapCollection();        // マップの集合を管理
    this.offset_x = 465;  // マップを表示する時の補正値
    this.offset_y = 250;

    // ボタン
    this.dayToId = [ '', 'btnD1', 'btnD2', 'btnD3' ];
    this.areaToId = [ '', 'btnE3', 'btnE4', 'btnW1', 'btnW2' ];
    this.scaleToId = [ '', 'btnUp', 'btnDw' ];

    this.idToDay = $H({btnD1: 1, btnD2: 2, btnD3: 3});
    this.idToArea = $H({btnE1: 1, btnE2: 1, btnE3: 1, btnE4: 2, btnE5: 2, btnE6: 2, btnW1: 3, btnW2: 4});
    this.idToScale = $H({btnUp: 1, btnDw: 2});
    this.areaNumToId = ['', 'btnE1', 'btnE2', 'btnE3', 'btnE4', 'btnE5', 'btnE6', 'btnW1', 'btnW2', 'btnE1'];
    this.dateIdToNum = $H({btnD1: 1, btnD2: 2, btnD3: 3});

    // 初期値設定
    this.selectedLocateId = "btnE2";  // エリア選択
    this.selectedDateId = "btnD1";    // 日付選択
    this.selectedScaleId = "btnDw";  // 拡大縮小選択

    // ボタンの位置情報（このエリア内はクリックされてもサークル情報を出さない）
    this.areaButtonPanel = new Rectangle(200, 5, 384, 25);
    this.dayButtonPanel = new Rectangle(5, 5, 165, 25);
    this.scaleButtonPanel = new Rectangle(5, 60, 30, 90);
    this.cursorButtonSelectPanel = new Rectangle(880, 5, 40, 25);
    this.cursorButtonPanel = new Rectangle(700, 260, 230, 230);
    this.cursorOn = false;

    // サークル情報
    this.circleInfo = new CircleInfo(map_id);

    // Ajax処理が終了したことを知らせるフラグ
    this.AjaxDone = false;

    // ID指定で開いている場合のみtrue
    this.openByIdNow = false;

    // マップ中央のスコープ
    this.scope = new Scope(map_id);
  },

  // -----------------------------------------------------------------------
  // マップ表示
  // -----------------------------------------------------------------------
  // 指定された日付＋エリア＋スケールの地図をセット
  setMap: function (comike_no, dayID, areaID, scaleID)
  {
    var map = this.mapCollection.load(this.MapID, comike_no, this.idToDay.get(dayID), this.idToArea.get(areaID), this.idToScale.get(scaleID), true);
//    var info = this.mapCollection.locateinfo.get(scaleID).get(areaID).toObject();
    var info = this.mapCollection.locateinfo[scaleID][areaID];
    map.move(-info.x + this.offset_x, -info.y + this.offset_y);
    map.showBitmapNear(info.x + this.offset_x, info.y + this.offset_y);
    return map;
  },

  // 表示位置はそのまま版
  setMapNoMove: function (comike_no, dayID, areaID, scaleID)
  {
    var pos = this.mapCollection.getCurrentMap().getPosition();
    var map = this.mapCollection.load(this.MapID, comike_no, this.idToDay.get(dayID), this.idToArea.get(areaID), this.idToScale.get(scaleID), true);
    map.setPosition(pos.x, pos.y);
    map.showBitmapNear(-pos.x + this.offset_x, -pos.y + this.offset_y);
    return map;
  },

  // ナビゲーションから選択された場合の処理
  setMapByAreaNum: function (comike_no, day, num, scale)
  {
    var map = this.setMap(comike_no, this.dayToId[day], this.areaNumToId[num], this.scaleToId[scale]);

    // ボタン選択
    this.dateSelect(this.dayToId[day], false);
    this.locationSelect(this.areaNumToId[num], false);
    this.scaleSelect(this.scaleToId[scale], false);

    // もし壁が選択されたら、そちらに視点を移動する
    if (num == 9) {
//      var info = this.mapCollection.locateinfo.get(this.scaleToId[scale]).get('btnE9').toObject();
      var info = this.mapCollection.locateinfo[this.scaleToId[scale]]['btnE9'];
      map.setPosition(-info.x + this.offset_x, -info.y + this.offset_y);
      map.showBitmapNear(info.x + this.offset_x, info.y + this.offset_y);
    }
  },

  // 指定された座標をセット
  setMapByLocate: function (comike_no, day, area, scale, x, y, funload)
  {
    // マップ表示
    var map = this.mapCollection.load(this.MapID, comike_no, day, area, scale, funload);
    map.move(-x + this.offset_x, -y + this.offset_y);
    map.showBitmapNear(parseInt(x) + this.offset_x, parseInt(y) + this.offset_y);

    // ボタン選択（表示だけ）
    this.dateSelect(this.dayToId[day], false);
    this.locationSelect(this._getCurrentArea(this.areaToId[area], x, y), false);
    this.scaleSelect(this.scaleToId[scale], false);
  },

  // -----------------------------------------------------------------------
  // デフォルト値で初期表示
  initialMapDefault: function ()
  {
    // スコープ表示
    this.scope.show();

    // コミケ番号を取得
    this.comikeNo = document.forms['ctrl'].comike_no.value;

    // 地図読み込み
    var map = this.mapCollection.load(this.MapID, this.comikeNo, this.idToDay.get(this.selectedDateId), this.idToArea.get(this.selectedLocateId), this.idToScale.get(this.selectedScaleId), false);

    // ボタン選択
    this.dateSelect(this.selectedDateId, true);
    this.locationSelect(this.selectedLocateId, true);
    this.scaleSelect(this.selectedScaleId, true);
  },

  // 初期表示用ルーチン（Parmalink）
  initialMapByParam: function (id)
  {
    // スコープ表示
    this.scope.show();

    var url = '/comike/map/api/getlocate';
    var param = 'id=' + id;
    this.AjaxDone = false;
    var myAjax = new Ajax.Request( url, {
      method: 'get', parameters: param, onComplete: function(Request) {
        try {
          var ret = eval('(' + Request.responseText + ')');
          if (ret.found) {
            control.comikeNo = ret.comike_no;
            // ボタンの初期値を設定
            control.selectedDateId = control.dayToId[ret.day];
            control.selectedLocateId = control.areaToId[ret.area];
            control.selectedScaleId = control.scaleToId[1]; // 拡大
            control.setMapByLocate(ret.comike_no, ret.day, ret.area, 1, parseInt(ret.x) + 15, parseInt(ret.y) + 15, false);
          } else {
            control.initialMapDefault();
          }
          control.AjaxDone = true;
        } catch(ex) {
         _MapInternalErrorMsg("データ解析時に異常が発生しました", ex, Request.responseText, 'initialMapByParam');
          control.AjaxDone = true;
        }
      }
    });

  // 上の処理が終わるまで待つ
    this.timerID = setInterval('control.waitForInitialMapByParam("' + id +'")', 200);
  },

  // initialMapByParamが終わってからサークル情報を表示する
  waitForInitialMapByParam: function(id)
  {
    if (this.AjaxDone) {
      clearInterval(this.timerID);
      this.openByIdNow = true;
      this.circleInfo.openById(id);
    }
  },

  // -----------------------------------------------------------------------
  // マウス制御
  // -----------------------------------------------------------------------
  // マウスが押された
  doMouseDown: function (event)
  {
    this.from.x = event.clientX;
    this.from.y = event.clientY;
    this.isClick = true;
  },

  // ドラッグ開始
   doStartDrag: function (x, y) {
//    this.scope.hide(); // フォーカスを消す
  },

  // ドラッグされた
  doDrag: function (event) {
    // マウスが動いたらクリックではない
    this.isClick = false;
  },

  // ドラッグ終了
  doEndDrag: function (event) {
    var pos = this.mapCollection.getCurrentMap().getPosition();
    var x = event.clientX - pos.x;
    var y = event.clientY - pos.y;

    // 周辺のビットマップを表示
    this.mapCollection.getCurrentMap().showBitmapNear(x, y);

    // 現在位置によってボタンの選択を変化させる
    nowArea = this._getCurrentArea(this.selectedLocateId, x, y);
    if (nowArea != this.selectedLocateId) {
      this.locationSelect(nowArea, false);
      this.selectedLocateId = nowArea;
    }

//    this.scope.show(); // フォーカスを表示
  },

  // クリックされた
  doClick: function (event) {
    var pos;
    // ドラッグだった場合は何もしない
    if (!this.isClick) {
      return ;
    }

    // 拡大時
    if (this.selectedScaleId == 'btnUp') {
      // ボタンをクリックしていなければ、サークル情報を表示する
      if ((!this.areaButtonPanel.isClick(event.clientX, event.clientY)) &&
          (!this.dayButtonPanel.isClick(event.clientX, event.clientY)) &&
          (!this.scaleButtonPanel.isClick(event.clientX, event.clientY)) &&
          (!this.cursorButtonSelectPanel.isClick(event.clientX, event.clientY)) &&
          (!(this.cursorOn && this.cursorButtonPanel.isClick(event.clientX, event.clientY)))) {
        pos = this.mapCollection.getCurrentMap().getPosition();
        // スクロール補正(for Opera, Safari)
        if (window.pageXOffset != undefined && window.pageYOffset != undefined) {
          pos.x -= window.pageXOffset;pos.y -= window.pageYOffset;
        }
        this.circleInfo.open(this.comikeNo, this.idToDay.get(this.selectedDateId), this.idToArea.get(this.selectedLocateId), event.clientX - pos.x, event.clientY - pos.y);
      }
    }
    // 縮小時
    if (this.selectedScaleId == 'btnDw') {
      // ボタンをクリックしていなければ、拡大する
      if ((!this.areaButtonPanel.isClick(event.clientX, event.clientY)) &&
          (!this.dayButtonPanel.isClick(event.clientX, event.clientY)) &&
          (!this.scaleButtonPanel.isClick(event.clientX, event.clientY)) &&
          (!this.cursorButtonSelectPanel.isClick(event.clientX, event.clientY)) &&
          (!(this.cursorOn && this.cursorButtonPanel.isClick(event.clientX, event.clientY)))) {
        this.scaleSelect('btnUp', false);
        pos = this._getScaleUpPos(this.mapCollection.getCurrentMap().getPosition(), event.clientX, event.clientY);
        // スクロール補正(for Opera, Safari)
        if (window.pageXOffset != undefined && window.pageYOffset != undefined) {
          pos.x -= window.pageXOffset;pos.y -= window.pageYOffset;
        }
        var map = this.setMap(this.comikeNo, this.selectedDateId, this.selectedLocateId, this.selectedScaleId);
        map.setPosition(pos.x, pos.y);
        map.showBitmapNear(-pos.x + this.offset_x, -pos.y + this.offset_y);
      }
    }
  },

  // -----------------------------------------------------------------------
  // ボタン
  // -----------------------------------------------------------------------
  // エリアの選択
  locationSelect: function (id, fChangeMap)
  {
    // ボタン表示の切り替え
    this._radioButtonSelectChange(id, this.selectedLocateId);
    this.selectedLocateId = id;

    // マップの切り替え
    if (fChangeMap) {
      var map = this.setMap(this.comikeNo, this.selectedDateId, this.selectedLocateId, this.selectedScaleId);
      // 周辺のビットマップを表示
      var pos = map.getPosition();
      var x = 465 - pos.x;
      var y = 250 - pos.y;
      map.showBitmapNear(x, y);
    }
  },

  // 日付の選択
  dateSelect: function (id, fChangeMap)
  {
    // ボタン表示の切り替え
    this._radioButtonSelectChange(id, this.selectedDateId);
    this.selectedDateId = id;

    // マップの切り替え（表示位置は移動せず）
    if (fChangeMap) {
      var map = this.setMapNoMove(this.comikeNo, this.selectedDateId, this.selectedLocateId, this.selectedScaleId);
      // 周辺のビットマップを表示
      var pos = map.getPosition();
      var x = 465 - pos.x;
      var y = 250 - pos.y;
      map.showBitmapNear(x, y);
    }
  },

  // スケールの選択
  scaleSelect: function (id, fChangeMap)
  {
    this._radioButtonSelectChange(id, this.selectedScaleId);
    var oldScaleId = this.selectedScaleId;
    this.selectedScaleId = id;

    // マップの切り替え
    if (fChangeMap && id != oldScaleId) {
      // スケールを切り替えた場合、座標もスケールに合わせて変更する
      var pos = this.mapCollection.getCurrentMap().getPosition();
      if (id == 'btnUp') {
        // 縮小→拡大
        pos = this._getScaleUpPos(pos, this.offset_x, this.offset_y);
        // カーソルキーのアイコン切り替え
        $('zoomicon').setAttribute('src', '/twitcomike/img/zoomout.png');
      } else {
        // 拡大→縮小
        pos = this._getScaleDownPos(pos, this.offset_x, this.offset_y);
        // カーソルキーのアイコン切り替え
        $('zoomicon').setAttribute('src', '/twitcomike/img/zoomin.png');
      }
      var map = this.setMap(this.comikeNo, this.selectedDateId, this.selectedLocateId, this.selectedScaleId);
      map.setPosition(pos.x, pos.y);
      // 周辺のビットマップを表示（拡大時）
//      if (id == 'btnUp') {
        pos = map.getPosition();
        var x = 465 - pos.x;
        var y = 250 - pos.y;
        map.showBitmapNear(x, y);
//      }
    }
  },

  // 拡大時の座標を求める
  _getScaleUpPos: function (pos, ox, oy)
  {
      pos.x = ox - pos.x;pos.y = oy - pos.y;
      pos.x = Math.round(pos.x * 6.4);pos.y = Math.round(pos.y * 6.4);
      pos.x -= ox;pos.y -= oy;
      pos.x = -pos.x;pos.y = -pos.y;
      return pos;
  },

  // 縮小時の座標を求める
  _getScaleDownPos: function (pos, ox, oy)
  {
      pos.x = ox - pos.x;pos.y = oy - pos.y;
      pos.x = Math.round(pos.x / 6.4);pos.y = Math.round(pos.y / 6.4);
      pos.x -= ox;pos.y -= oy;
      pos.x = -pos.x;pos.y = -pos.y;
      return pos;
  },

  // ボタン表示切り替え用サブルーチン
  _radioButtonSelectChange: function (newid, oldid)
  {
	  if (newid != oldid) {
		var newclass = this._radioButtonOn(newid);
       var oldclass = this._radioButtonOff(oldid);
       $(newid).className = newclass;
       $(oldid).className = oldclass;
     } else {
    	// newidのclassnameを常に-onにする 
 		var newclass = this._radioButtonOn(newid);
        $(newid).className = newclass;
      }
  },

  // ボタンのクラス名を押された状態にする
  _radioButtonOn:function (id)
  {
    var classname = $(id).className;
    var matches = classname.match(/^(.+)-on$/);
    if (!matches) {
        classname = classname + '-on';
    }
    return classname;
  },

  // ボタンのクラス名を押されない状態にする
  _radioButtonOff:function (id)
  {
    var classname = $(id).className;
    var matches = classname.match(/^(.+)-on$/);
    if (matches) {
        classname = matches[1];
    }
    return classname;
  },

  // ボタンのクラス名を切り替える
  _radioButtonToggle:function (id)
  {
    var classname = $(id).className;
    var matches = classname.match(/^(.+)-on$/);
    if (matches) {
        classname = matches[1];
    } else {
        classname = classname + '-on';
    }
    return classname;
  },

  // 現在の座標がどのエリアなのかをボタンのIDで返す
  _getCurrentArea: function (curLocateId, x, y)
  {
    // 西館なら、エリアに関係なく現在のボタンID
    if (curLocateId == 'btnW1' || curLocateId == 'btnW2') {
      return curLocateId;
    }

    // 東館の場合、x座標から判定
    if (this.idToArea[curLocateId] == 1) {
      if (this._cmpArea('btnE1', x)) {return 'btnE1';};
      if (this._cmpArea('btnE2', x)) {return 'btnE2';};
      if (this._cmpArea('btnE3', x)) {return 'btnE3';};
    }
    if (this.idToArea[curLocateId] == 2) {
      if (this._cmpArea('btnE4', x)) {return 'btnE4';};
      if (this._cmpArea('btnE5', x)) {return 'btnE5';};
      if (this._cmpArea('btnE6', x)) {return 'btnE6';};
    }

    // わかんない時は今の値を返す
    return curLocateId;
  },

  _cmpArea: function (id, x) {
//    var info = this.mapCollection.locateinfo.get(this.selectedScaleId).get(id).toObject();
    var info = this.mapCollection.locateinfo[this.selectedScaleId][id];
    x += (this.offset_x / 4);
    // もし基準点が画像をはみ出た場合、基準点は画像の一番右とする
    if ((id == 'btnE1' || id == 'btnE6') && x > (info.origin + info.width)) {
      x = info.origin + info.width;
    }
    return (x >= info.origin && x <= (info.origin + info.width)) ? true : false;
  },

  // ボタンによるマップのスクロール
  scrollMapSelect: function (vx, vy) {
    // 移動する
    var map = this.mapCollection.getCurrentMap();
//    var mapinfo = this.mapCollection.mapinfo.get(map.id).toObject();
    var mapinfo = this.mapCollection.mapinfo[map.id];
    var pos = map.getPosition();
    if ((pos.y + vy) < -mapinfo.height || (pos.y + vy) > 500 ||
        (pos.x + vx) < -mapinfo.width || (pos.x + vx) > 930) {
        // 範囲外なら停止する
        this.endScrollMap();
        return ;
    }
    map.move(vx, vy);

    // 周辺のビットマップを表示
    var x = 465 - pos.x;
    var y = 250 - pos.y;
    map.showBitmapNear(x, y);

    // 現在位置によってボタンの選択を変化させる
    nowArea = this._getCurrentArea(this.selectedLocateId, x, y);
    if (nowArea != this.selectedLocateId) {
      this.locationSelect(nowArea, false);
      this.selectedLocateId = nowArea;
    }
  },

  // マップの自動スクロールを開始
  beginScrollMap: function (id, vx, vy) {
      this.endScrollMap();   // もしまだイベントが残っていた場合、それを停止する
      
      $(id).setAttribute('class', 'btn-cursorselect-on');
      this.scrollMapSelect(vx, vy); // レスポンスをよく見せるため、まず最初にスクロール
      this.scrollMapCallback = function() { control.scrollMapSelect(vx, vy); };
      this.scrollMapTimer = new PeriodicalExecuter(this.scrollMapCallback, 0.2);
      this.scrollMapCurId = id;
  },

  // マップの自動スクロールを終了
  endScrollMap: function () {
      if (typeof this.scrollMapTimer != 'undefined') {
          this.scrollMapTimer.stop();
          delete this.scrollMapTimer;
          delete this.scrollMapCallback;
          $(this.scrollMapCurId).setAttribute('class', 'btn-cursor');
      }
  },

  // ボタンによるクリック
  clickSelect: function() {
     var e = new Object;
     e.type = "click";
     e.clientX = 465;
     e.clientY = 250;
     this.isClick = true;
     this.doClick(e);
  },

  // カーソルを表示・非表示
  toggleCursor: function() {
    this.cursorOn = !this.cursorOn;
    Element.toggle('btn-cursor-panel');
    if (this.cursorOn) {
        $('btnCursor').setAttribute('class', 'btn-cursorselect-on');
    } else {
        $('btnCursor').setAttribute('class', 'btn-cursorselect');
    }
  },

  // 拡大・縮小トグルボタン
  toggleScale: function() {
    var newId = (this.selectedScaleId == 'btnUp' ? 'btnDw' : 'btnUp');
    this.scaleSelect(newId, true);
  },

  // -----------------------------------------------------------------------
  // サークル情報
  // -----------------------------------------------------------------------
  // サークル情報を開く
  openCircleInfo: function (circle)
  {
    this.circleInfo._openCirclePanel(circle);
  },

  // 登録がない場合はリンクのみを通知するウィンドウを開く
  openCircleNoEntry: function (circle)
  {
    this.circleInfo._openNoEntryCirclePanel(circle);
  },

  // サークル情報を閉じる
  closeCircleInfo: function (pass)
  {
    // サークル情報を閉じる
    this.circleInfo.close(pass);

    // このクリックがドラッグ開始と誤解されないため、ここでフラグを落とす
    this.isDrag = false;
    this.isClick = false;
  },

  // twitterに投稿する
  doTwit: function ()
  {
    var status = 'http://twitcmap.jp/' + control.circleInfo.circle.hash + ' '
               + control.circleInfo.circle.locate + ' '
               + control.circleInfo.circle.name + ' '
               + '#twitcmap #comike';
    var link = "http://twitter.com/home?status=" + encodeURIComponent(status);
    window.open(link, "twitter");
  },

  // -----------------------------------------------------------------------
  // トラックバック
  // -----------------------------------------------------------------------
  showTrackbackInfo: function(showHash)
  {
    window.parent.document.forms['tb'].id.value = this.circleInfo.circle.hash;
    window.parent.document.forms['tb'].space.value = this.circleInfo.circle.space;
    window.parent.document.forms['tb'].show.value = (showHash? "true" : "false");
    window.parent.document.forms['tb'].twitter_user.value = this.circleInfo.circle.twitter_user;
    window.parent.document.forms['tb'].twitter_image.value = this.circleInfo.circle.twitter_image;
    window.parent.document.forms['tb'].submit.click();
  },

  hideTrackbackInfo: function()
  {
    window.parent.document.forms['tb'].hide.click();
  }
};


