/**
 * Name: Spell your sister
 * User: Arrowing
 * Date: 2013-4-22
 * Version: 1.0
 */

var SYS = function(SYSHelp, undefined){
  var doc = document,

  /* 基本常量配置 */
    cLang = {
      DIFFICULTY: [9, 16, 25], /* 难度 */
      THUMB: 'thumb', /* 缩略图名称 */
      THUMB_ID: 'thumb', /* 缩略图ID */
      ITEM_CLASS: 'sys-item', /* 拼图小块类名 */
      MOVABLE_CLASS: 'movable', /* 可移动图片类名 */
      NOTICE_ID: 'notice', /* 信息板提示区域ID */
      STEPS_ID: 'steps', /* 信息板记录步数ID */
      LABEL_ID: 'label', /* 信息板提示文字ID */
      DATE_ID: 'date', /* 信息板记录时间ID */
      RELOAD_ID: 'reload', /* 重载操作按钮ID */
      CHANGE_DIFF_ID: 'change_diff', /* 更改难度按钮ID */
      CHANGE_PIC_ID: 'change_pic' /* 更改图片按钮ID */
    };

  function SYS(options){
    /* 继承事件类型 */
    if(!options.sys){
      EventTarget.call(this);

      /* 绑定事件触发器 */
      if(options.events instanceof Object){
        for(var eventType in options.events){
          this.addEvent(eventType, options.events[eventType]);
        };
      };
    }

    /* 可写配置 */
    this.cellNum = parseInt(options.cellNum) || 9, /* 难度 */
      this.containerId = options.containerId, /* 拼图容器ID */
      this.imgPath = options.imgPath, /* 拼图的存放路径 */
      this.imgExt = options.imgExt || '.jpg', /* 拼图后缀名 */
      this.containerWidth = options.containerWidth || 480, /* 容器宽度 */

      /* 其他配置 */
      this.finishTargetNum = this.cellNum - 1, /* 完成拼图需要小块图片的正确数目 */
      this.finishCurrentNum = parseInt(options.finishCurrentNum) || 0, /* 当前正确数目 */
      this.emptyCellIndex = !isNaN(options.emptyCellIndex) ? parseInt(options.emptyCellIndex) : this.finishTargetNum, /* 当前拼图哪个位置为空 */
      this.containerNode = doc.getElementById(this.containerId), /* 拼图的容器节点 */
      this.cellNumPerRow = Math.sqrt(this.cellNum), /* 拼图每行有几个格子 */
      this.sideLen = this.containerWidth / this.cellNumPerRow, /* 每个小块图片的边长 */
      this.rightSortPic = options.rightSortPic || null, /* 正确的图片排序索引 */
      this.inMove = false, /* 是否在移动中 */
      this.allPicNodes = [], /* 当前拼图的所有图片节点NodeList */
      this.movableRange = null, /* 可移动的范围 */
      this.finish = false, /* 是否完成拼图 */
      this.timer = null, /* 计时timer */
      this.recordStepsNode = doc.getElementById(cLang.STEPS_ID), /* 记录已走步数的节点 */
      this.recordDateNode = doc.getElementById(cLang.DATE_ID), /* 记录时间的节点 */
      this.score = options.score || 0,/* 分数 */
      this.isInNormal = true,/* 是否在正常时间内完成 */
      this.thumbNode = doc.getElementById(cLang.THUMB_ID), /* 缩略图的节点 */
      this.thumbNode.src = this.imgPath + '/' + cLang.THUMB + this.imgExt, /* 载入缩略图 */
      this.isContinue = typeof options.isContinue == 'boolean' ? options.isContinue : false, /* 是否继续游戏 */
      this.continueData = options.continueData;/* 继续游戏的数据 */
  };

  /* 继承事件类型的原型对象 */
  SYSHelp.extendClass(SYS, EventTarget);

  /* 简单的渐进动画 */
  function __animate(options){
    var now, styleDirection,
      step = options.step || 100,
      direction = options.direction,
      node = options.node,
      end = options.end;

    styleDirection = ( direction == 'bottom' ? 'top' :
      (direction == 'right' ? 'left' : null) );

    switch (direction){
      case 'top':
      case 'left':
        now = parseInt(node.style[direction]) - step;
        if(now <= end){
          node.style[direction] = end + 'px';
          options.callback && options.callback();
          return;
        }else{
          node.style[direction] = now + 'px';
        };
        break;
      case 'bottom':
      case 'right':
        now = parseInt(node.style[styleDirection]) + step;
        if(now >= end){
          node.style[styleDirection] = end + 'px';
          options.callback && options.callback();
          return;
        }else{
          node.style[styleDirection] = now + 'px';
        };
        break;
    };
    setTimeout(SYSHelp.bind(arguments.callee, null, options), 30);
  };

  /* 初始化 */
  SYS.prototype.init = function(isFirst){
    /* 可移动便移动 */
    var inMove, moveX, moveY, node,
      __getNodeFromIndex = function(index){
        for(var i=0,len=this.allPicNodes.length;i<len;i++){
          if(this.allPicNodes[i].getAttribute('index') == index){
            return this.allPicNodes[i];
          }
        }
      },
      __setUp = function(e){
        if(inMove) return;
        e.target.classList.contains(cLang.MOVABLE_CLASS) && this.move(e.target);
      },
      __setDown = function(e){
        moveX = e.pageX;
        moveY = e.pageY;
        inMove = false;
        node = null;
      },
      __setMove = function(e){
        var disX, disY;
        if(inMove) return;

        disX = e.pageX - moveX;
        disY = e.pageY - moveY;

        if(disX > 30){//向右移动
          node = __getNodeFromIndex.call(this, this.emptyCellIndex - 1);
        }else if(disX < -30){//向左移动
          node = __getNodeFromIndex.call(this, this.emptyCellIndex + 1);
        }else if(disY > 30){//向下移动
          node = __getNodeFromIndex.call(this, this.emptyCellIndex - this.cellNumPerRow);
        }else if(disY < -30){//向上移动
          node = __getNodeFromIndex.call(this, this.emptyCellIndex + this.cellNumPerRow);
        }else{
          inMove = false;
          return;
        }

        node && node.classList.contains(cLang.MOVABLE_CLASS) && this.move(node);
        inMove = true;
      };

    if(isFirst){/* 绑定事件 */
      /* 拼图事件 */
      //SYSHelp.addEventListener(this.containerNode, 'MSPointerDown', SYSHelp.bind(__setDown, this));
      //SYSHelp.addEventListener(this.containerNode, 'MSPointerMove', SYSHelp.bind(__setMove, this));
      SYSHelp.addEventListener(this.containerNode, 'click', SYSHelp.bind(__setUp, this));

      /* 重载拼图事件 */
      SYSHelp.addEventListener(doc.getElementById(cLang.RELOAD_ID), 'click', SYSHelp.bind(this.reload, this));

      /* 更改难度事件 */
      SYSHelp.addEventListener(doc.getElementById(cLang.CHANGE_DIFF_ID), 'click', SYSHelp.bind(this.changeDiff, this));
    }

    this.__create();
  };

  /* 创建拼图 */
  SYS.prototype.__create = function(){
    var iPicIndex, sHtml = '',
      aRandom, picIndex, theSrc,

    /* 创建一个有序数组 */
      createRandomArray = function(){
        var i, aRandom = [];
        for(i=0;i<this.finishTargetNum;i++){
          aRandom.push(i);
        };
        return aRandom;
      },

    /* 从有序的数组中获取随机数 */
      __getRandomItem = function(array){
        return array.splice(Math.floor(Math.random() * array.length), 1);
      },

    /* 获取图片绝对位置 */
      __getPositionFromNum = function(num){
        var row = Math.floor(num / this.cellNumPerRow),
          col = num % this.cellNumPerRow,
          left = col * this.sideLen,
          top = row * this.sideLen;

        return 'style="left:'+ left +'px;top:'+ top +'px;"';
      };

    /* 重置参数 */
    this.stopRunTime();
    this.inMove = false;
    this.inChange = false;

    if(this.isContinue){ /* 假如启动游戏后的第一次继续游戏，仅载入数据 */
      this.recordStepsNode.innerHTML = this.continueData.steps;
      this.recordDateNode.innerHTML = this.continueData.date;
      this.containerNode.innerHTML = this.continueData.html;
      this.isContinue = false;
    }else{
      aRandom = createRandomArray.call(this);
      this.rightSortPic = [];
      this.finishCurrentNum = 0;

      for(iPicIndex=0;iPicIndex<this.finishTargetNum;iPicIndex++){
        picIndex = __getRandomItem(aRandom); /* 正确的图片索引 */
        (picIndex == iPicIndex) && this.finishCurrentNum++; /* 假如图片索引等于位置索引，则正确，完成拼图小块数加一 */
        this.rightSortPic.push(picIndex); /* 保存图片正确的索引，以确认是否拼对 */
        theSrc = this.imgPath + '/' + this.cellNum + '/' + picIndex + this.imgExt;
        sHtml += '<img width="'+ this.sideLen +'" height="'+ this.sideLen +'" index="'+ iPicIndex +'" '+ __getPositionFromNum.call(this, iPicIndex) +' class="'+ cLang.ITEM_CLASS +'" src="'+ theSrc +'" />';
      };

      this.finish = false;
      this.emptyCellIndex = this.finishTargetNum;
      this.score = this.cellNum * 5000;
      this.recordDateNode.innerHTML = this.recordStepsNode.innerHTML = 0;
      this.containerNode.innerHTML = sHtml;
      this.startRunTime();
    }

    this.allPicNodes = this.containerNode.getElementsByClassName(cLang.ITEM_CLASS);
    this.__calMovaleRange();
  };

  /* 移动某可移动的图片 */
  SYS.prototype.move = function(node){
    var index = node.getAttribute('index'),
      direction = this.movableRange[index],
      subScore, end,
      callback = function(){
        var nodeIndex = SYSHelp.getIndex(node, this.allPicNodes);

        (this.rightSortPic[nodeIndex] == index) && this.finishCurrentNum--; /* 本来对的，走错，完成数减一 */
        (this.rightSortPic[nodeIndex] == this.emptyCellIndex) && this.finishCurrentNum++;/* 走对，完成数加一 */
        node.setAttribute('index', this.emptyCellIndex);

        if(this.finishCurrentNum == this.finishTargetNum){/* 假如完成数达标，则完成拼图 */
          this.__finish();
          this.fireEvent('onMoveEnd');
          return;
        };

        this.emptyCellIndex = parseInt(index);
        this.__calMovaleRange();
        this.inMove = false;
        this.fireEvent('onMoveEnd');
      };

    if(this.inMove) return false;
    this.inMove = true;

    switch (direction){
      case 'top':
      case 'left':
        end = parseInt(node.style[direction]) - this.sideLen;
        break;
      case 'bottom':
        end = parseInt(node.style['top']) + this.sideLen;
        break;
      case 'right':
        end = parseInt(node.style['left']) + this.sideLen;
        break;
    };

    if(typeof end == 'number'){
      this.fireEvent('onMove');
      __animate({
        node: node, direction: direction, end: end,
        callback: SYSHelp.bind(callback, this)
      });

      /* 计算分数（计算公式）
       * 基础分 ： 5000 * 难度(9|16|25)
       * 每过一秒扣300分，每走一步扣100分
       * 超过(90|160|250)秒的秒数不计扣分，步数则改为扣（随机：1-50）分/秒
       * 假如分数低于5000，每步扣1分
       */

      if(this.score <= 5000){
        subScore = 1;
      }else if(this.isInNormal){
        subScore = 100;
      }else{
        subScore = Math.floor(Math.random() * 50);
      }
      this.score -= subScore;

      this.recordStepsNode.innerHTML = parseInt(this.recordStepsNode.innerHTML) + 1;
    }else{
      this.inMove = false;
    };
  };

  /* 完成拼图 */
  SYS.prototype.__finish = function(){
    var lastImg,
      xy = this.sideLen * (this.cellNumPerRow - 1);

    this.stop();

    /* 补上空缺的图 */
    lastImg = doc.createElement('img');
    this.containerNode.appendChild(lastImg);
    lastImg.src = this.imgPath + '/' + this.cellNum + '/' + this.finishTargetNum + this.imgExt;
    lastImg.className = cLang.ITEM_CLASS;
    lastImg.style.cssText = 'width:'+this.sideLen+'px;height:'+this.sideLen+'px;left:'+ xy +'px;top:'+ xy +'px;';

    this.fireEvent('onFinish');
  };

  /* 根据当前空单元格计算可移动的单元格 */
  SYS.prototype.__calMovaleRange = function (){
    var top, bottom, left, right, movableRange,
      i, node, index;

    /* 可以移动的图片，上方 */
    top = ((top = this.emptyCellIndex - this.cellNumPerRow) < 0 ? null : top);
    /* 可以移动的图片，下方 */
    bottom = ((bottom = this.emptyCellIndex + this.cellNumPerRow) > this.finishTargetNum ? null : bottom);
    /* 可以移动的图片，左方 */
    left = (this.emptyCellIndex % this.cellNumPerRow == 0 ? null : this.emptyCellIndex - 1);
    /* 可以移动的图片，右方 */
    right = ((this.emptyCellIndex + 1) % this.cellNumPerRow == 0 ? null : this.emptyCellIndex + 1);

    movableRange = {top: top, bottom: bottom, left: left, right: right};
    top !== null && (movableRange[top] = 'bottom');/* 如果top变量不为空，图片索引为top变量的元素可以下移 */
    bottom !== null && (movableRange[bottom] = 'top');
    left !== null && (movableRange[left] = 'right');
    right !== null && (movableRange[right] = 'left');

    for(i=0;i<this.finishTargetNum;i++){
      node = this.allPicNodes[i];
      index = node.getAttribute('index');

      if(movableRange[index]){
        node.classList.add(cLang.MOVABLE_CLASS);
      }else if(this.movableRange && this.movableRange[index]){ /* 判断点击的元素是否为上一步可移动的格子，移除可移动class */
        node.classList.remove(cLang.MOVABLE_CLASS);
      };
    };

    this.movableRange = movableRange;
  },

    /* 停止拼图 */
    SYS.prototype.stop = function(){
      this.finish = true;
      SYSHelp.removeClass(this.allPicNodes, cLang.MOVABLE_CLASS);
      this.stopRunTime();
      this.fireEvent('onStop');
    },

    /* 开始计时 */
    SYS.prototype.startRunTime = function(){
      var timing = function(){
          var seconds = parseInt(this.recordDateNode.innerHTML);
          this.recordDateNode.innerHTML = seconds + 1;

          /* 正常完成时间：(90|160|250) */
          this.isInNormal = seconds <= this.cellNum * 10 ? true : false;
          if(this.isInNormal){
            this.score -= 300;
          }
        },
        timingBind = SYSHelp.bind(timing, this);

      this.timer = setInterval(timingBind, 1000);
      this.fireEvent('onStartRunTime');
    },

    /* 停止计时 */
    SYS.prototype.stopRunTime = function(){
      clearInterval(this.timer);
      this.timer = null;
      this.fireEvent('onStopRunTime');
    },

    /* 重新载入拼图 */
    SYS.prototype.reload = function(){
      if(this.inChange) return;
      this.inChange = true;
      this.__create();
      this.fireEvent('onReload');
    };

  /* 更改难度 */
  SYS.prototype.changeDiff = function(difficulty){
    var diffIndex;

    if(typeof difficulty == 'number'){
      this.cellNum = difficulty;
    }else{
      diffIndex = SYSHelp.getIndex(this.cellNum, cLang.DIFFICULTY) + 1;
      if(diffIndex >= cLang.DIFFICULTY.length){
        diffIndex = 0;
      };
      this.cellNum = cLang.DIFFICULTY[diffIndex];
    };

    this.finishTargetNum = this.cellNum - 1;
    this.cellNumPerRow = Math.sqrt(this.cellNum);
    this.sideLen = this.containerWidth / this.cellNumPerRow;

    /* 游戏进行中配置的话即刻重载 */
    !(typeof difficulty == 'number') && this.reload();
  };

  return {
    createSYS: function(options){
      var isFirst = true,
        oSYS = options.sys || new SYS(options);

      if(options.sys){
        SYS.apply(oSYS, [options]);
        isFirst = false;
      }

      oSYS.init(isFirst);

      return oSYS;
    }
  };
}(SYSHelp);