// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

base.require('base.guid');
base.require('base.rect');
base.require('base.raf');
base.require('tracing.trace_model.object_instance');
base.require('cc.picture_as_canvas');
base.require('cc.util');

base.exportTo('cc', function() {

  var ObjectSnapshot = tracing.trace_model.ObjectSnapshot;

  // Number of pictures created. Used as an uniqueId because we are immutable.
  var PictureCount = 0;

  /**
   * @constructor
   */
  function PictureSnapshot() {
    ObjectSnapshot.apply(this, arguments);
    this.guid_ = base.GUID.allocate();
  }

  PictureSnapshot.CanRasterize = function() {
    if (!window.chrome)
      return false;
    if (!window.chrome.skiaBenchmarking)
      return false;
    if (!window.chrome.skiaBenchmarking.rasterize)
      return false;
    return true;
  }

  PictureSnapshot.CanGetOps = function() {
    if (!window.chrome)
      return false;
    if (!window.chrome.skiaBenchmarking)
      return false;
    if (!window.chrome.skiaBenchmarking.getOps)
      return false;
    return true;
  }

  PictureSnapshot.HowToEnablePictureDebugging = function() {
    var usualReason = [
      'For pictures to show up, you need to have Chrome running with ',
      '--enable-skia-benchmarking. Please restart chrome with this flag ',
      'and try again.'
    ].join('');

    if (!window.chrome)
      return usualReason;
    if (!window.chrome.skiaBenchmarking)
      return usualReason;
    if (!window.chrome.skiaBenchmarking.rasterize)
      return 'Your chrome is old';
    if (!window.chrome.skiaBenchmarking.getOps)
      return 'Your chrome is old, skiaBenchmarking.getOps not found';
    return 'Rasterizing is on';
  }

  PictureSnapshot.prototype = {
    __proto__: ObjectSnapshot.prototype,

    preInitialize: function() {
      cc.preInitializeObject(this);
      this.rasterResult_ = undefined;
    },

    initialize: function() {
      if (!this.args.params.layerRect)
        throw new Error('Missing layer rect');
      this.layerRect_ = this.args.params.layerRect;
      this.layerRect_ = base.Rect.FromArray(this.layerRect_);
    },

    get layerRect() {
      return this.layerRect_;
    },

    get guid() {
      return this.guid_;
    },

    getBase64SkpData: function() {
      return this.args.skp64;
    },

    getOps: function() {
      if (!PictureSnapshot.CanGetOps()) {
        console.error(PictureSnapshot.HowToEnablePictureDebugging());
        return undefined;
      }

      var ops = window.chrome.skiaBenchmarking.getOps({
        skp64: this.args.skp64,
        params: {
          layer_rect: this.args.params.layerRect,
          opaque_rect: this.args.params.opaqueRect
        }
      });

      if (!ops)
        console.error('Failed to get picture ops.');

      return ops;
    },

    /**
     * Rasterize the picture.
     *
     * @param {{opt_stopIndex: number, params}} The SkPicture operation to
     *     rasterize up to. If not defined, the entire SkPicture is rasterized.
     * @param {function(cc.PictureAsCanvas)} The callback function that is
     *     called after rasterization is complete or fails.
     */
    rasterize: function(params, rasterCompleteCallback) {
      if (!PictureSnapshot.CanRasterize() || !PictureSnapshot.CanGetOps()) {
        rasterCompleteCallback(new cc.PictureAsCanvas(
            this, cc.PictureSnapshot.HowToEnablePictureDebugging()));
        return;
      }

      var raster = window.chrome.skiaBenchmarking.rasterize(
          {
            skp64: this.args.skp64,
            params: {
              layer_rect: this.args.params.layerRect,
              opaque_rect: this.args.params.opaqueRect
            }
          },
          {
            stop: params.stopIndex === undefined ? -1 : params.stopIndex,
            params: { }
          });

      if (raster) {
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        canvas.width = raster.width;
        canvas.height = raster.height;
        var imageData = ctx.createImageData(raster.width, raster.height);
        imageData.data.set(new Uint8ClampedArray(raster.data));
        ctx.putImageData(imageData, 0, 0);
        rasterCompleteCallback(new cc.PictureAsCanvas(this, canvas));
      } else {
        var error = 'Failed to rasterize picture. ' +
                'Your recording may be from an old Chrome version. ' +
                'The SkPicture format is not backward compatible.';
        rasterCompleteCallback(new cc.PictureAsCanvas(this, error));
      }
    }
  };

  ObjectSnapshot.register('cc::Picture', PictureSnapshot);

  return {
    PictureSnapshot: PictureSnapshot
  };
});