$(function () {

  Aj.init(function ($scope) {
    $scope.data = {};
    $scope.observeData = {
      list: []
    };

    $scope.observe($scope.data, {
      value: function(newValue, oldValue){
        $scope.observeData.value = newValue + "-observed";
      },
      list: {
        _array_map: function(newValue, oldValue, bindContext){
          var list = $scope.observeData.list;
          var hopeLength = Array.isArray(newValue) ? newValue.length : 0;
          Aj.arrayUtil.arrayLengthAdjust(list, hopeLength, function(){//initialize new item
            return "";
          }, function(item, index){//discard mapped items
            //if necessary, this is a chance to clear the resource of mapped item before they are removed
            //item.discard()
          });
          return list;
        },
        _array_discard: function(bindContext){
          delete $scope.observeData.list;
          //$scope.observeData.list = [];
        },
        _item: {
          _value: function(newValue, oldValue, bindContext){
            var suffix = "-observed-changed";
            var mappedItem = bindContext._mappedArray[bindContext._arrayIndex];
            //mapped item should equal to initial value "" or the oldValue + "-observed-changed"
            if(mappedItem === "" || mappedItem === (oldValue + suffix)){
              //is ok
            }else{
              throw "value of mappedItem is not correct, got:" + mappedItem + "  but expect:" + (oldValue + suffix);
            }
            var targetIndex = bindContext._getArrayIndex();
            $scope.observeData.list[targetIndex] = $scope.data.list[targetIndex] + suffix;
          }
        }
      }
    });
    
    $scope.snippet("body")
      .bind($scope.data, {
        value: [
          ".x-value",
          Aj.form({selector: "#value-input"}, null, ["keyup"])
        ],
        list : {
          _duplicator : "li.row",
          _item : [
            //2 way on input
            {
              _selector : "[name=input]",
              _render : function (target, newValue, oldValue) {
                target.val(newValue);
              },
              _register_dom_change : function(target, changeHandler, bindContext){
                target.keyup(function(){
                  var v = $(this).val();
                  changeHandler(v, bindContext);
                });
                return function(){
                  changeHandler(target.val(), bindContext);
                }
              }
            },
            //1 way
            "#preview",
            //binding _index
            {
              _index : ".x-index",
              _context: ".x-func"
            }
          ],
          length : ".x-length"
        }
      })
      .bind($scope.observeData, {
        value: ".x-value-ob",
        list : {
          _duplicator : "li.row-ob",
          _item : [
            //1 way
            "#preview-ob",
            //binding _index
            {
              _index : ".x-index-ob"
            }
          ],
          length : ".x-length-ob"
        }
      })
      .on("click", ".x-add", function () {
        Aj.getContext(this).getArrayAssistant().after("added value" + new Date());
      })
      .on("click", ".x-remove", function () {
        Aj.getContext(this).getArrayAssistant().remove()
      })
      .on("click", ".x-go-up", function () {
        Aj.getContext(this).getArrayAssistant().moveUp()
      })
      .on("click", ".x-go-down", function () {
        Aj.getContext(this).getArrayAssistant().moveDown()
      })
      .bind("#set-list-value", "click", function () {
        var v = $("#list-data-input").val();
        var list = v.split("\n");
        $scope.data.list = list;
      });

  });

});
