/**
 * * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Generated by Apache Flex Cross-Compiler from org/apache/flex/binding/MXMLBeadViewDataBinding.as
 * org.apache.flex.binding.MXMLBeadViewDataBinding
 *
 * @fileoverview
 *
 * @suppress {checkTypes|accessControls}
 */

goog.provide('org.apache.flex.binding.MXMLBeadViewDataBinding');

goog.require('org.apache.flex.binding.ConstantBinding');
goog.require('org.apache.flex.binding.GenericBinding');
goog.require('org.apache.flex.binding.PropertyWatcher');
goog.require('org.apache.flex.binding.SimpleBinding');
goog.require('org.apache.flex.core.DataBindingBase');
goog.require('org.apache.flex.core.IBead');
goog.require('org.apache.flex.core.IStrand');
goog.require('org.apache.flex.events.IEventDispatcher');
goog.require('org.apache.flex.utils.Language');



/**
 *  Constructor.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10.2
 *  @playerversion AIR 2.6
 *  @productversion FlexJS 0.0
 * @constructor
 * @extends {org.apache.flex.core.DataBindingBase}
 * @implements {org.apache.flex.core.IBead}
 */
org.apache.flex.binding.MXMLBeadViewDataBinding = function() {
  
  this.deferredBindings = {};
  org.apache.flex.binding.MXMLBeadViewDataBinding.base(this, 'constructor');
};
goog.inherits(org.apache.flex.binding.MXMLBeadViewDataBinding, org.apache.flex.core.DataBindingBase);


/**
 * @private
 * @type {org.apache.flex.core.IStrand}
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype._strand;


/**
 * @private
 * @param {org.apache.flex.events.Event} event
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.initCompleteHandler = function(event) {
  var /** @type {Object} */ fieldWatcher;
  var /** @type {org.apache.flex.binding.SimpleBinding} */ sb;
  if (!("_bindings" in this._strand))
    return;
  var /** @type {Array} */ bindingData = this._strand["_bindings"];
  var /** @type {number} */ n = Number(bindingData[0]);
  var /** @type {Array} */ bindings = [];
  var /** @type {number} */ i;
  var /** @type {number} */ index = 1;
  for (i = 0; i < n; i++) {
    var /** @type {Object} */ binding = {};
    binding.source = bindingData[index++];
    binding.destFunc = bindingData[index++];
    binding.destination = bindingData[index++];
    bindings.push(binding);
  }
  var /** @type {Object} */ watchers = this.decodeWatcher(bindingData.slice(index));
  for (i = 0; i < n; i++) {
    binding = bindings[i];
    if (org.apache.flex.utils.Language.is(binding.source, Array)) {
      if (binding.source[0] in this._strand) {
        if (binding.source.length == 2 && binding.destination.length == 2) {
          var /** @type {Object} */ destObject;
          var /** @type {org.apache.flex.core.IStrand} */ destination;
          var /** @type {Object} */ modelWatcher = watchers.watcherMap[binding.source[0]];
          fieldWatcher = modelWatcher.children.watcherMap[binding.source[1]];
          if (org.apache.flex.utils.Language.is(fieldWatcher.eventNames, String)) {
            sb = new org.apache.flex.binding.SimpleBinding();
            sb.destinationPropertyName = org.apache.flex.utils.Language.string(binding.destination[1]);
            sb.eventName = org.apache.flex.utils.Language.as(fieldWatcher.eventNames, String);
            sb.sourceID = org.apache.flex.utils.Language.string(binding.source[0]);
            sb.sourcePropertyName = org.apache.flex.utils.Language.string(binding.source[1]);
            sb.setDocument(this._strand);
            destObject = this._strand[binding.destination[0]];
            destination = org.apache.flex.utils.Language.as(destObject, org.apache.flex.core.IStrand);
            if (destination)
              destination.addBead(sb); else {
              if (destObject) {
                sb.destination = destObject;
                this._strand.addBead(sb);
              } else {
                this.deferredBindings[binding.destination[0]] = sb;
                org.apache.flex.utils.Language.as(this._strand, org.apache.flex.events.IEventDispatcher, true).addEventListener("valueChange", org.apache.flex.utils.Language.closure(this.deferredBindingsHandler, this, 'deferredBindingsHandler'));
              }
            }
          } else if (fieldWatcher.eventNames == null) {
            var /** @type {org.apache.flex.binding.ConstantBinding} */ cb = new org.apache.flex.binding.ConstantBinding();
            cb.destinationPropertyName = org.apache.flex.utils.Language.string(binding.destination[1]);
            cb.sourceID = org.apache.flex.utils.Language.string(binding.source[0]);
            cb.sourcePropertyName = org.apache.flex.utils.Language.string(binding.source[1]);
            cb.setDocument(this._strand);
            destObject = this._strand[binding.destination[0]];
            destination = org.apache.flex.utils.Language.as(destObject, org.apache.flex.core.IStrand);
            if (destination)
              destination.addBead(cb); else {
              if (destObject) {
                cb.destination = destObject;
                this._strand.addBead(cb);
              } else {
                this.deferredBindings[binding.destination[0]] = cb;
                org.apache.flex.utils.Language.as(this._strand, org.apache.flex.events.IEventDispatcher, true).addEventListener("valueChange", org.apache.flex.utils.Language.closure(this.deferredBindingsHandler, this, 'deferredBindingsHandler'));
              }
            }
          }
        }
      }
    } else if (org.apache.flex.utils.Language.is(binding.source, String)) {
      fieldWatcher = watchers.watcherMap[binding.source];
      if (org.apache.flex.utils.Language.is(fieldWatcher.eventNames, String)) {
        sb = new org.apache.flex.binding.SimpleBinding();
        sb.destinationPropertyName = org.apache.flex.utils.Language.string(binding.destination[1]);
        sb.eventName = org.apache.flex.utils.Language.as(fieldWatcher.eventNames, String);
        sb.sourcePropertyName = org.apache.flex.utils.Language.string(binding.source);
        sb.setDocument(this._strand);
        destObject = this._strand[binding.destination[0]];
        destination = org.apache.flex.utils.Language.as(destObject, org.apache.flex.core.IStrand);
        if (destination)
          destination.addBead(sb); else {
          if (destObject) {
            sb.destination = destObject;
            this._strand.addBead(sb);
          } else {
            this.deferredBindings[binding.destination[0]] = sb;
            org.apache.flex.utils.Language.as(this._strand, org.apache.flex.events.IEventDispatcher, true).addEventListener("valueChange", org.apache.flex.utils.Language.closure(this.deferredBindingsHandler, this, 'deferredBindingsHandler'));
          }
        }
      }
    } else {
      this.makeGenericBinding(binding, i, watchers);
    }
  }
};


/**
 * @private
 * @param {Object} binding
 * @param {number} index
 * @param {Object} watchers
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.makeGenericBinding = function(binding, index, watchers) {
  var /** @type {org.apache.flex.binding.GenericBinding} */ gb = new org.apache.flex.binding.GenericBinding();
  gb.setDocument(this._strand);
  gb.destinationData = binding.destination;
  gb.destinationFunction = binding.destFunc;
  gb.source = binding.source;
  this.setupWatchers(gb, index, watchers.watchers, null);
};


/**
 * @private
 * @param {org.apache.flex.binding.GenericBinding} gb
 * @param {number} index
 * @param {Array} watchers
 * @param {org.apache.flex.binding.WatcherBase} parentWatcher
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.setupWatchers = function(gb, index, watchers, parentWatcher) {
  var /** @type {boolean} */ foundWatcher = false;
  var /** @type {number} */ n = watchers.length;
  for (var /** @type {number} */ i = 0; i < n; i++) {
    var /** @type {Object} */ watcher = watchers[i];
    var /** @type {boolean} */ isValidWatcher = false;
    if (typeof((watcher.bindings)) == "number")
      isValidWatcher = (watcher.bindings == index);
    else
      isValidWatcher = (watcher.bindings.indexOf(index) != -1);
    if (isValidWatcher) {
      var /** @type {string} */ type = org.apache.flex.utils.Language.string(watcher.type);
      switch (type) {
        case "property":
          var /** @type {org.apache.flex.binding.PropertyWatcher} */ pw = new org.apache.flex.binding.PropertyWatcher(this, watcher.propertyName, watcher.eventNames, watcher.getterFunction);
          watcher.watcher = pw;
          if (parentWatcher)
            pw.parentChanged(parentWatcher.value);
          else
            pw.parentChanged(this._strand);
          if (parentWatcher)
            parentWatcher.addChild(pw);
          if (watcher.children == null)
            pw.addBinding(gb);
          foundWatcher = true;
          break;
      }
      if (watcher.children) {
        this.setupWatchers(gb, index, watcher.children.watchers, watcher.watcher);
      }
    }
  }
  if (!foundWatcher && parentWatcher == null) {
    gb.valueChanged(null);
  }
};


/**
 * @private
 * @param {Array} bindingData
 * @return {Object}
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.decodeWatcher = function(bindingData) {
  var /** @type {Object} */ watcherMap = {};
  var /** @type {Array} */ watchers = [];
  var /** @type {number} */ n = bindingData.length;
  var /** @type {number} */ index = 0;
  var /** @type {Object} */ watcherData;
  while (index < n - 2) {
    var /** @type {number} */ watcherIndex = Number(bindingData[index++]);
    var /** @type {number} */ type = Number(bindingData[index++]);
    switch (type) {
      case 0:
        watcherData = {type:"function"};
        watcherData.functionName = bindingData[index++];
        watcherData.paramFunction = bindingData[index++];
        watcherData.eventNames = bindingData[index++];
        watcherData.bindings = bindingData[index++];
        break;
      case 1:
        watcherData = {type:"static"};
        watcherData.propertyName = bindingData[index++];
        watcherData.eventNames = bindingData[index++];
        watcherData.bindings = bindingData[index++];
        watcherData.getterFunction = bindingData[index++];
        watcherData.parentObj = bindingData[index++];
        watcherMap[watcherData.propertyName] = watcherData;
        break;
      case 2:
        watcherData = {type:"property"};
        watcherData.propertyName = bindingData[index++];
        watcherData.eventNames = bindingData[index++];
        watcherData.bindings = bindingData[index++];
        watcherData.getterFunction = bindingData[index++];
        watcherMap[watcherData.propertyName] = watcherData;
        break;
      case 3:
        watcherData = {type:"xml"};
        watcherData.propertyName = bindingData[index++];
        watcherData.bindings = bindingData[index++];
        watcherMap[watcherData.propertyName] = watcherData;
        break;
    }
    watcherData.children = bindingData[index++];
    if (watcherData.children != null) {
      watcherData.children = this.decodeWatcher(watcherData.children);
    }
    watcherData.index = watcherIndex;
    watchers.push(watcherData);
  }
  return {watchers:watchers, watcherMap:watcherMap};
};


/**
 * @private
 * @type {Object}
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.deferredBindings;


/**
 * @private
 * @param {org.apache.flex.events.Event} event
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.deferredBindingsHandler = function(event) {
  for (var /** @type {string} */ p in this.deferredBindings) {
    if (this._strand[p] != null) {
      var /** @type {org.apache.flex.core.IStrand} */ destination = org.apache.flex.utils.Language.as(this._strand[p], org.apache.flex.core.IStrand);
      if (destination)
        destination.addBead(this.deferredBindings[p]); else {
        var /** @type {Object} */ destObject = this._strand[p];
        if (destObject) {
          this.deferredBindings[p].destination = destObject;
          this._strand.addBead(this.deferredBindings[p]);
        } else {
          org.apache.flex.utils.Language.trace("unexpected condition in deferredBindingsHandler");
        }
      }
      delete this.deferredBindings[p];
    }
  }
};


Object.defineProperties(org.apache.flex.binding.MXMLBeadViewDataBinding.prototype, /** @lends {org.apache.flex.binding.MXMLBeadViewDataBinding.prototype} */ {
/** @export */
strand: {
set: /** @this {org.apache.flex.binding.MXMLBeadViewDataBinding} */ function(value) {
  this._strand = value;
  org.apache.flex.utils.Language.as(this._strand, org.apache.flex.events.IEventDispatcher, true).addEventListener("initBindings", org.apache.flex.utils.Language.closure(this.initCompleteHandler, this, 'initCompleteHandler'));
}}}
);


/**
 * Metadata
 *
 * @type {Object.<string, Array.<Object>>}
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.FLEXJS_CLASS_INFO = { names: [{ name: 'MXMLBeadViewDataBinding', qName: 'org.apache.flex.binding.MXMLBeadViewDataBinding'}], interfaces: [org.apache.flex.core.IBead] };


/**
 * Prevent renaming of class. Needed for reflection.
 */
goog.exportSymbol('org.apache.flex.binding.MXMLBeadViewDataBinding', org.apache.flex.binding.MXMLBeadViewDataBinding);



/**
 * Reflection
 *
 * @return {Object.<string, Function>}
 */
org.apache.flex.binding.MXMLBeadViewDataBinding.prototype.FLEXJS_REFLECTION_INFO = function () {
  return {
    variables: function () {
      return {
      };
    },
    accessors: function () {
      return {
        'strand': { type: 'IStrand', declaredBy: 'org.apache.flex.binding.MXMLBeadViewDataBinding'}
      };
    },
    methods: function () {
      return {
        'MXMLBeadViewDataBinding': { type: '', declaredBy: 'org.apache.flex.binding.MXMLBeadViewDataBinding'}
      };
    }
  };
};