text: var Blocks = require('./blocks');
  var Variable = require('../engine/variable');
  var List = require('../engine/list');
  var uid = require('../util/uid');
  
  /**
   * @fileoverview
   * A Target is an abstract "code-running" object for the Scratch VM.
   * Examples include sprites/clones or potentially physical-world devices.
   */
  
  /**
   * @param {?Blocks} blocks Blocks instance for the blocks owned by this target.
   * @constructor
   */
  var Target = function (blocks) {
      if (!blocks) {
          blocks = new Blocks(this);
      }
      /**
       * A unique ID for this target.
       * @type {string}
       */
      this.id = uid();
      /**
       * Blocks run as code for this target.
       * @type {!Blocks}
       */
      this.blocks = blocks;
      /**
       * Dictionary of variables and their values for this target.
       * Key is the variable name.
       * @type {Object.<string,*>}
       */
      this.variables = {};
      /**
       * Dictionary of lists and their contents for this target.
       * Key is the list name.
       * @type {Object.<string,*>}
       */
      this.lists = {};
  };
  
  /**
   * Called when the project receives a "green flag."
   * @abstract
   */
  Target.prototype.onGreenFlag = function () {};
  
  /**
   * Return a human-readable name for this target.
   * Target implementations should override this.
   * @abstract
   * @returns {string} Human-readable name for the target.
   */
  Target.prototype.getName = function () {
      return this.id;
  };
  
  /**
   * Look up a variable object, and create it if one doesn't exist.
   * Search begins for local variables; then look for globals.
   * @param {!string} name Name of the variable.
   * @return {!Variable} Variable object.
   */
  Target.prototype.lookupOrCreateVariable = function (name) {
      // If we have a local copy, return it.
      if (this.variables.hasOwnProperty(name)) {
          return this.variables[name];
      }
      // If the stage has a global copy, return it.
      if (this.runtime && !this.isStage) {
          var stage = this.runtime.getTargetForStage();
          if (stage.variables.hasOwnProperty(name)) {
              return stage.variables[name];
          }
      }
      // No variable with this name exists - create it locally.
      var newVariable = new Variable(name, 0, false);
      this.variables[name] = newVariable;
      return newVariable;
  };
  
  /**
  * Look up a list object for this target, and create it if one doesn't exist.
  * Search begins for local lists; then look for globals.
  * @param {!string} name Name of the list.
  * @return {!List} List object.
   */
  Target.prototype.lookupOrCreateList = function (name) {
      // If we have a local copy, return it.
      if (this.lists.hasOwnProperty(name)) {
          return this.lists[name];
      }
      // If the stage has a global copy, return it.
      if (this.runtime && !this.isStage) {
          var stage = this.runtime.getTargetForStage();
          if (stage.lists.hasOwnProperty(name)) {
              return stage.lists[name];
          }
      }
      // No list with this name exists - create it locally.
      var newList = new List(name, []);
      this.lists[name] = newList;
      return newList;
  };
  
  /**
   * Post/edit sprite info.
   * @param {object} data An object with sprite info data to set.
   * @abstract
   */
  Target.prototype.postSpriteInfo = function () {};
  
  /**
   * Call to destroy a target.
   * @abstract
   */
  Target.prototype.dispose = function () {};
  
  module.exports = Target;
  