// Generated by CoffeeScript 1.6.3
var BAKAZE_TO_STR, TSUPAIS, TSUPAI_TO_IMAGE_NAME, cloneBoard, comparePais, currentActionId, currentKyokuId, currentViewpoint, deleteTehai, dumpBoard, getCurrentKyoku, goBack, goNext, initPlayers, kyokus, loadAction, paiToImageUrl, parsePai, playerInfos, removeRed, renderAction, renderCurrentAction, renderHo, renderPai, renderPais, ripai, sortPais, _base, _base1;

window.console || (window.console = {});

(_base = window.console).log || (_base.log = function() {});

(_base1 = window.console).error || (_base1.error = function() {});

TSUPAIS = [null, "E", "S", "W", "N", "P", "F", "C"];

TSUPAI_TO_IMAGE_NAME = {
  "E": "ji_e",
  "S": "ji_s",
  "W": "ji_w",
  "N": "ji_n",
  "P": "no",
  "F": "ji_h",
  "C": "ji_c"
};

BAKAZE_TO_STR = {
  "E": "東",
  "S": "南",
  "W": "西",
  "N": "北"
};

kyokus = [];

currentKyokuId = 0;

currentActionId = 0;

currentViewpoint = 0;

playerInfos = [{}, {}, {}, {}];

parsePai = function(pai) {
  if (pai.match(/^([1-9])(.)(r)?$/)) {
    return {
      type: RegExp.$2,
      number: parseInt(RegExp.$1),
      red: RegExp.$3 ? true : false
    };
  } else {
    return {
      type: "t",
      number: TSUPAIS.indexOf(pai),
      red: false
    };
  }
};

comparePais = function(lhs, rhs) {
  var lhsRep, parsedLhs, parsedRhs, rhsRep;
  parsedLhs = parsePai(lhs);
  lhsRep = parsedLhs.type + parsedLhs.number + (parsedLhs.red ? "1" : "0");
  parsedRhs = parsePai(rhs);
  rhsRep = parsedRhs.type + parsedRhs.number + (parsedRhs.red ? "1" : "0");
  if (lhsRep < rhsRep) {
    return -1;
  } else if (lhsRep > rhsRep) {
    return 1;
  } else {
    return 0;
  }
};

sortPais = function(pais) {
  return pais.sort(comparePais);
};

paiToImageUrl = function(pai, pose) {
  var ext, name, parsedPai, redSuffix;
  if (pai) {
    if (pai === "?") {
      name = "bk";
      ext = "gif";
    } else {
      parsedPai = parsePai(pai);
      if (parsedPai.type === "t") {
        name = TSUPAI_TO_IMAGE_NAME[pai];
      } else {
        redSuffix = parsedPai.red ? "r" : "";
        name = "" + parsedPai.type + "s" + parsedPai.number + redSuffix;
      }
      ext = parsedPai.red ? "png" : "gif";
    }
    if (pose === void 0) {
      pose = 1;
    }
    return "files/images/p_" + name + "_" + pose + "." + ext;
  } else {
    return "files/images/blank.png";
  }
};

cloneBoard = function(board) {
  var bk, bv, newBoard, newPlayer, pk, player, pv, _i, _len;
  newBoard = {};
  for (bk in board) {
    bv = board[bk];
    if (bk === "players") {
      newBoard[bk] = [];
      for (_i = 0, _len = bv.length; _i < _len; _i++) {
        player = bv[_i];
        newPlayer = {};
        for (pk in player) {
          pv = player[pk];
          newPlayer[pk] = pv;
        }
        newBoard[bk].push(newPlayer);
      }
    } else {
      newBoard[bk] = bv;
    }
  }
  return newBoard;
};

initPlayers = function(board) {
  var player, _i, _len, _ref, _results;
  _ref = board.players;
  _results = [];
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    player = _ref[_i];
    player.tehais = null;
    player.furos = [];
    player.ho = [];
    player.reach = false;
    _results.push(player.reachHoIndex = null);
  }
  return _results;
};

removeRed = function(pai) {
  if (!pai) {
    return null;
  }
  if (pai.match(/^(.+)r$/)) {
    return RegExp.$1;
  } else {
    return pai;
  }
};

loadAction = function(action) {
  var actorPlayer, board, furos, i, kyoku, pai, prevBoard, targetPlayer, _i, _j, _k, _l, _len, _len1, _m, _n, _o, _ref, _ref1, _ref2;
  if (kyokus.length > 0) {
    kyoku = kyokus[kyokus.length - 1];
    board = cloneBoard(kyoku.actions[kyoku.actions.length - 1].board);
  } else {
    kyoku = null;
    board = null;
  }
  if (board && ("actor" in action)) {
    actorPlayer = board.players[action.actor];
  } else {
    actorPlayer = null;
  }
  if (board && ("target" in action)) {
    targetPlayer = board.players[action.target];
  } else {
    targetPlayer = null;
  }
  switch (action.type) {
    case "start_game":
      for (i = _i = 0; _i < 4; i = ++_i) {
        playerInfos[i].name = action.names[i];
      }
      break;
    case "end_game":
      null;
      break;
    case "start_kyoku":
      kyoku = {
        actions: [],
        bakaze: action.bakaze,
        kyokuNum: action.kyoku,
        honba: action.honba
      };
      kyokus.push(kyoku);
      prevBoard = board;
      board = {
        players: [{}, {}, {}, {}],
        doraMarkers: [action.dora_marker]
      };
      initPlayers(board);
      for (i = _j = 0; _j < 4; i = ++_j) {
        board.players[i].tehais = action.tehais[i];
        if (prevBoard) {
          board.players[i].score = prevBoard.players[i].score;
        } else {
          board.players[i].score = 25000;
        }
      }
      break;
    case "end_kyoku":
      null;
      break;
    case "tsumo":
      actorPlayer.tehais = actorPlayer.tehais.concat([action.pai]);
      break;
    case "dahai":
      deleteTehai(actorPlayer, action.pai);
      actorPlayer.ho = actorPlayer.ho.concat([action.pai]);
      break;
    case "reach":
      actorPlayer.reachHoIndex = actorPlayer.ho.length;
      break;
    case "reach_accepted":
      actorPlayer.reach = true;
      break;
    case "chi":
    case "pon":
    case "daiminkan":
      targetPlayer.ho = targetPlayer.ho.slice(0, targetPlayer.ho.length - 1);
      _ref = action.consumed;
      for (_k = 0, _len = _ref.length; _k < _len; _k++) {
        pai = _ref[_k];
        deleteTehai(actorPlayer, pai);
      }
      actorPlayer.furos = actorPlayer.furos.concat([
        {
          type: action.type,
          taken: action.pai,
          consumed: action.consumed,
          target: action.target
        }
      ]);
      break;
    case "ankan":
      _ref1 = action.consumed;
      for (_l = 0, _len1 = _ref1.length; _l < _len1; _l++) {
        pai = _ref1[_l];
        deleteTehai(actorPlayer, pai);
      }
      actorPlayer.furos = actorPlayer.furos.concat([
        {
          type: action.type,
          consumed: action.consumed
        }
      ]);
      break;
    case "kakan":
      deleteTehai(actorPlayer, action.pai);
      actorPlayer.furos = actorPlayer.furos.concat([]);
      furos = actorPlayer.furos;
      for (i = _m = 0, _ref2 = furos.length; 0 <= _ref2 ? _m < _ref2 : _m > _ref2; i = 0 <= _ref2 ? ++_m : --_m) {
        if (furos[i].type === "pon" && removeRed(furos[i].taken) === removeRed(action.pai)) {
          furos[i] = {
            type: "kakan",
            taken: action.pai,
            consumed: action.consumed,
            target: furos[i].target
          };
        }
      }
      break;
    case "hora":
    case "ryukyoku":
      null;
      break;
    case "dora":
      board.doraMarkers = board.doraMarkers.concat([action.dora_marker]);
      break;
    case "error":
      null;
      break;
    default:
      throw "unknown action: " + action.type;
  }
  if (action.scores) {
    for (i = _n = 0; _n < 4; i = ++_n) {
      board.players[i].score = action.scores[i];
    }
  }
  if (kyoku) {
    for (i = _o = 0; _o < 4; i = ++_o) {
      if (action.actor !== void 0 && i !== action.actor) {
        ripai(board.players[i]);
      }
    }
    action.board = board;
    return kyoku.actions.push(action);
  }
};

deleteTehai = function(player, pai) {
  var idx;
  player.tehais = player.tehais.concat([]);
  idx = player.tehais.lastIndexOf(pai);
  if (idx < 0) {
    idx = player.tehais.lastIndexOf("?");
  }
  if (idx < 0) {
    throw "pai not in tehai";
  }
  return player.tehais[idx] = null;
};

ripai = function(player) {
  var pai;
  if (player.tehais) {
    player.tehais = (function() {
      var _i, _len, _ref, _results;
      _ref = player.tehais;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        pai = _ref[_i];
        if (pai) {
          _results.push(pai);
        }
      }
      return _results;
    })();
    return sortPais(player.tehais);
  }
};

dumpBoard = function(board) {
  var consumedStr, furo, hoStr, i, player, tehaisStr, _i, _j, _len, _ref, _results;
  _results = [];
  for (i = _i = 0; _i < 4; i = ++_i) {
    player = board.players[i];
    if (player.tehais) {
      tehaisStr = player.tehais.join(" ");
      _ref = player.furos;
      for (_j = 0, _len = _ref.length; _j < _len; _j++) {
        furo = _ref[_j];
        consumedStr = furo.consumed.join(" ");
        tehaisStr += " [" + furo.taken + "/" + consumedStr + "]";
      }
      console.log("[" + i + "] tehais: " + tehaisStr);
    }
    if (player.ho) {
      hoStr = player.ho.join(" ");
      _results.push(console.log("[" + i + "] ho: " + hoStr));
    } else {
      _results.push(void 0);
    }
  }
  return _results;
};

renderPai = function(pai, view, pose) {
  if (pose === void 0) {
    pose = 1;
  }
  view.attr("src", paiToImageUrl(pai, pose));
  switch (pose) {
    case 1:
      view.addClass("pai");
      return view.removeClass("laid-pai");
    case 3:
      view.addClass("laid-pai");
      return view.removeClass("pai");
    default:
      throw "unknown pose";
  }
};

renderPais = function(pais, view, poses) {
  var i, _i, _ref, _results;
  pais || (pais = []);
  poses || (poses = []);
  view.resize(pais.length);
  _results = [];
  for (i = _i = 0, _ref = pais.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
    _results.push(renderPai(pais[i], view.at(i), poses[i]));
  }
  return _results;
};

renderHo = function(player, offset, pais, view) {
  var i, reachIndex, _i, _ref, _results;
  if (player.reachHoIndex === null) {
    reachIndex = null;
  } else {
    reachIndex = player.reachHoIndex - offset;
  }
  view.resize(pais.length);
  _results = [];
  for (i = _i = 0, _ref = pais.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
    _results.push(renderPai(pais[i], view.at(i), i === reachIndex ? 3 : 1));
  }
  return _results;
};

renderAction = function(action) {
  var dir, displayAction, furo, furoView, ho, i, infoView, j, k, kyoku, laidPos, pais, player, poses, v, view, wanpais, _i, _j, _ref, _ref1, _ref2, _ref3;
  displayAction = {};
  for (k in action) {
    v = action[k];
    if (k !== "board" && k !== "logs") {
      displayAction[k] = v;
    }
  }
  $("#action-label").text(JSON.stringify(displayAction, null, 2));
  $("#log-label").text((action.logs && action.logs[currentViewpoint]) || "");
  kyoku = getCurrentKyoku();
  for (i = _i = 0; _i < 4; i = ++_i) {
    player = action.board.players[i];
    view = Dytem.players.at((i - currentViewpoint + 4) % 4);
    infoView = Dytem.playerInfos.at(i);
    infoView.score.text(player.score);
    infoView.viewpoint.text(i === currentViewpoint ? "+" : "");
    if (!player.tehais) {
      renderPais([], view.tehais);
      view.tsumoPai.hide();
    } else if (player.tehais.length % 3 === 2) {
      renderPais(player.tehais.slice(0, player.tehais.length - 1), view.tehais);
      view.tsumoPai.show();
      renderPai(player.tehais[player.tehais.length - 1], view.tsumoPai);
    } else {
      renderPais(player.tehais, view.tehais);
      view.tsumoPai.hide();
    }
    ho = player.ho || [];
    renderHo(player, 0, ho.slice(0, 6), view.hoRows.at(0).pais);
    renderHo(player, 6, ho.slice(6, 12), view.hoRows.at(1).pais);
    renderHo(player, 12, ho.slice(12), view.hoRows.at(2).pais);
    view.furos.resize(player.furos.length);
    if (player.furos) {
      j = player.furos.length - 1;
      while (j >= 0) {
        furo = player.furos[j];
        furoView = view.furos.at(player.furos.length - 1 - j);
        if (furo.type === "ankan") {
          pais = ["?"].concat(furo.consumed.slice(0, 2)).concat(["?"]);
          poses = [1, 1, 1, 1];
        } else {
          dir = (4 + furo.target - i) % 4;
          if ((_ref = furo.type) === "daiminkan" || _ref === "kakan") {
            laidPos = [null, 3, 1, 0][dir];
          } else {
            laidPos = [null, 2, 1, 0][dir];
          }
          pais = furo.consumed.concat([]);
          poses = [1, 1, 1];
          [].splice.apply(pais, [laidPos, laidPos - laidPos].concat(_ref1 = [furo.taken])), _ref1;
          [].splice.apply(poses, [laidPos, laidPos - laidPos].concat(_ref2 = [3])), _ref2;
        }
        renderPais(pais, furoView.pais, poses);
        --j;
      }
    }
  }
  wanpais = ["?", "?", "?", "?", "?", "?"];
  for (i = _j = 0, _ref3 = action.board.doraMarkers.length; 0 <= _ref3 ? _j < _ref3 : _j > _ref3; i = 0 <= _ref3 ? ++_j : --_j) {
    wanpais[i + 2] = action.board.doraMarkers[i];
  }
  return renderPais(wanpais, Dytem.wanpais);
};

getCurrentKyoku = function() {
  return kyokus[currentKyokuId];
};

renderCurrentAction = function() {
  return renderAction(getCurrentKyoku().actions[currentActionId]);
};

goNext = function() {
  if (currentActionId === getCurrentKyoku().actions.length - 1) {
    return;
  }
  ++currentActionId;
  $("#action-id-label").val(currentActionId);
  return renderCurrentAction();
};

goBack = function() {
  if (currentActionId === 0) {
    return;
  }
  --currentActionId;
  $("#action-id-label").val(currentActionId);
  return renderCurrentAction();
};

$(function() {
  var action, bakazeStr, honba, i, j, kyokuNum, label, playerInfoView, playerView, _i, _j, _k, _l, _len, _ref;
  $(window).bind("mousewheel", function(e) {
    e.preventDefault();
    if (e.originalEvent.wheelDelta < 0) {
      return goNext();
    } else if (e.originalEvent.wheelDelta > 0) {
      return goBack();
    }
  });
  $("#prev-button").click(goBack);
  $("#next-button").click(goNext);
  $("#go-button").click(function() {
    currentActionId = parseInt($("#action-id-label").val());
    return renderCurrentAction();
  });
  $("#kyokuSelector").change(function() {
    currentKyokuId = parseInt($("#kyokuSelector").val());
    currentActionId = 0;
    return renderCurrentAction();
  });
  $("#viewpoint-button").click(function() {
    currentViewpoint = (currentViewpoint + 1) % 4;
    return renderCurrentAction();
  });
  for (_i = 0, _len = allActions.length; _i < _len; _i++) {
    action = allActions[_i];
    loadAction(action);
  }
  Dytem.init();
  for (i = _j = 0; _j < 4; i = ++_j) {
    playerView = Dytem.players.append();
    playerView.addClass("player-" + i);
    for (j = _k = 0; _k < 3; j = ++_k) {
      playerView.hoRows.append();
    }
    playerInfoView = Dytem.playerInfos.append();
    playerInfoView.index.text(i);
    playerInfoView.name.text(playerInfos[i].name);
  }
  for (i = _l = 0, _ref = kyokus.length; 0 <= _ref ? _l < _ref : _l > _ref; i = 0 <= _ref ? ++_l : --_l) {
    bakazeStr = BAKAZE_TO_STR[kyokus[i].bakaze];
    honba = kyokus[i].honba;
    kyokuNum = kyokus[i].kyokuNum;
    label = "" + bakazeStr + kyokuNum + "局 " + honba + "本場";
    $("#kyokuSelector").get(0).options[i] = new Option(label, i);
  }
  console.log("loaded");
  return renderCurrentAction();
});
