"use strict";

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Creates a container with reference to actual object (asset created from some file) and information
 * about loading process of that object.
 *
 * @author smrceant (Antonin Smrcek)
 *
 * @param {string}                  name                  name under which this asset can be looked up in global list
 * @param {Asset.AssetType}         type                  asset type
 * @param {*}                       emptyObjectInstance   reference to application object (e.g. Mesh), it is empty, but initialized
 *                                                        which is important (we can return this object to requesting jobs even if it is not fully loaded yet)
 * @param {AssetJob}                job                   job which is creating/loading file of this asset
 * @constructor
 */
var Asset = function (name, type, emptyObjectInstance, job)
{
  /**
   * Name under which this asset can be looked up in global list.
   *
   * @type {string}
   */
  this.name = name;

  /**
   * Asset type.
   *
   * @type {Asset.AssetType}
   */
  this.type = type;

  /**
   * Reference to application object (e.g. Mesh), it is empty, but initialized.
   *
   * @type {*}
   */
  this.createdObject = emptyObjectInstance;

  /**
   * Job which is creating/loading file of this asset.
   *
   * @type {AssetJob}
   */
  this.job  = job;

  /**
   * Is the asset finished loading?
   * @type {boolean}
   */
  this.finished = false;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * The asset must wait for running until the requiredAssetOrAssetJob FULLY finishes.
 * Normally, it waits until it starts executing or something like that.
 *
 * @param {Asset|AssetJob}  requiredAssetOrAssetJob   job which must be totally finished for this job to be able to start
 */
Asset.prototype.waitWithRunningForFinish = function (requiredAssetOrAssetJob)
{
  var proxy  = assetLoader.makeDummyJob("proxy", false);
  proxy.waitForFinish(requiredAssetOrAssetJob);

  this.waitFor (proxy);
};

/**
 * Standard method, which makes this job wait for other job to at least start, I think.
 *
 * @param {Asset|AssetJob} requiredAssetOrAssetJob
 * @param {boolean}        [waitForFinish]
 */
Asset.prototype.waitFor = function (requiredAssetOrAssetJob, waitForFinish)
{
  if (!Util.isInitialized(waitForFinish))
  {
    var waitForFinish = false;
  }

  if (!Util.isInitialized(requiredAssetOrAssetJob))
  {
    console.error("Invalid asset to wait for - it does not exist.");
    return;
  }

  // we were given an Asset object
  if (requiredAssetOrAssetJob instanceof Asset)
  {
    this.job.addRequiredJob (requiredAssetOrAssetJob.job, waitForFinish);
  }
  // we were given Asset.job object
  else
  {
    this.job.addRequiredJob (requiredAssetOrAssetJob, waitForFinish);
  }
};

/**
 *
 * @param {Asset|AssetJob} requiredAssetOrAssetJob
 */
Asset.prototype.waitForFinish = function (requiredAssetOrAssetJob)
{
  this.waitFor (requiredAssetOrAssetJob, true);
};

/**
 * Starts the job associated with this asset.
 */
Asset.prototype.startJob = function()
{
  this.job.start();
};

/**
 * Retrieves object which was downloaded during the downloading phase of this asset's job.
 *
 * @returns {*}
 */
Asset.prototype.getCreatedObject = function()
{
  if (this.type !== Asset.AssetType.TEXT)
  {
    return this.createdObject;
  }
  else
  {
    return this.job.getDownloadedData();
  }
};

/**
 * Retrieves text from the text assets.
 *
 * @returns {*}
 */
Asset.prototype.getText = function()
{
  if (this.type !== Asset.AssetType.TEXT)
  {
    console.error("Asset " + this.name + " is not a TEXT asset, cannot use this method.");
    return null;
  }
  else
  {
    return this.getCreatedObject();
  }
};

/**
 * Is the asset finished loading?
 *
 * @returns {boolean}
 */
Asset.prototype.isFinished = function()
{
  return this.finished;
};

/**
 * Marks asset as finished loading.
 */
Asset.prototype.markFinished = function()
{
  this.finished = true;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ASSET TYPES
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Asset.AssetType =
{
  IMAGE:              0,
  SCENE_DEF:          1,
  TEXT:               2,
  JSON:               3,

  DUMMY:              4,
  DUMMY_START_ITSELF: 5
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
