/*
* Author   Jonathan Lurie - http://me.jonahanlurie.fr
* License  MIT
* Link      https://github.com/jonathanlurie/pixpipejs
* Lab       MCIN - Montreal Neurological Institute
*/

import { Image2D } from '../core/Image2D.js';
import { Filter } from '../core/Filter.js';

/**
* CanvasImageWriter is a filter to output an instance of Image into a
* HTML5 canvas element.
* The metadata "parentDivID" has to be set using `setMetadata("parentDivID", "whatever")`
* The metadata "alpha", if true, enable transparency. Default: false.
* If the input Image2D has values not in [0, 255], you can remap/stretch using
* setMetadata("min", xxx ) default: 0
* setMetadata("max", xxx ) default: 255
*
* usage: examples/imageToCanvasFilter.html
*
* @example
// create an image
* var myImage = new pixpipe.Image2D({width: 100, height: 250, color: [255, 128, 64, 255]})
*
* // create a filter to write the image into a canvas
* var imageToCanvasFilter = new pixpipe.CanvasImageWriter( "myDiv" );
* imageToCanvasFilter.addInput( myImage );
* imageToCanvasFilter.update();
*/
class CanvasImageWriter extends Filter{

  /**
  * @param {String} parentDivID - dom id of the future canvas' parent.
  * (most likely the ID of a div)
  */
  constructor(){
    // call Filter constructor
    super();

    this._inputValidator[ 0 ] = Image2D.TYPE();
    this.setMetadata("alpha", false);
    this.setMetadata("min", 0);
    this.setMetadata("max", 255);


    // so that we can flush the content
    this._canvas = null;
    this._ctx = null;
  }


  /**
  * [PRIVATE]
  * Initialize a new canvas object
  */
  _init(){

    var parentElem = document.getElementById( this.getMetadata("parentDivID") );
    while (parentElem.firstChild) {
        parentElem.removeChild(parentElem.firstChild);
    }

    // creating a canvas element
    this._canvas = document.createElement("canvas");
    this._canvas.style = "image-rendering: pixelated;";
    this._ctx = this._canvas.getContext('2d');

    // not sure this is useful since the style is "pixelated"
    // (does not seem to well super well with Firefox)
    this._ctx.imageSmoothingEnabled = true;
    this._ctx.mozImageSmoothingEnabled = false;
    this._ctx.webkitImageSmoothingEnabled = false;
    this._ctx.ctxmsImageSmoothingEnabled = false;

    document.getElementById(this.getMetadata("parentDivID")).appendChild(this._canvas);
  }


  /**
  * Overwrite the generic (empty) method.
  */
  _run(){
    var that = this;

    // abort if invalid input
    if(!this.hasValidInput() )
      return;

    var image = this._input[0];
    var ncppSrc = image.getComponentsPerPixel();

    // only Image2d with 1 or 4 bands can be displayed
    if( ncppSrc != 1 && ncppSrc != 4){
      console.warn("Cannot write Image in canvas if contains other than 1 or 4 bands.");
      return;
    }

    if(!this.getMetadata("parentDivID")){
      console.error("The parent DIV ID to place the canvas element was not specified. Unable to display anything.");
      return;
    }

    // build a new canvas
    this._init();
    var useAlphaBand = this.getMetadata("alpha");

    // resizing the canvas
    this._canvas.width = image.getWidth();
    this._canvas.height = image.getHeight();

    var canvasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height);
    var canvasImageDataArray = canvasImageData.data;

    // getting Image object data
    var originalImageDataArray = image.getData();

    // input image is RGBA
    if(ncppSrc == 4){
      // copying the data into the canvas array (clamped uint8)
      originalImageDataArray.forEach( function(value, index){
        if(!useAlphaBand && index%4 == 3){
          canvasImageDataArray[index] = 255;
        }else{
          canvasImageDataArray[index] = that._stretchMinMax(value);
        }
      });

    // input image is mono chanel
    }else if(ncppSrc == 1){
      originalImageDataArray.forEach( function(value, index){
        var index1D = index*4;
        var stretchedValue = that._stretchMinMax(value);
        canvasImageDataArray[index1D] = stretchedValue;
        canvasImageDataArray[index1D + 1] = stretchedValue;
        canvasImageDataArray[index1D + 2] = stretchedValue;
        canvasImageDataArray[index1D + 3] = 255;
      });

    // input image is RGB
    }else if(ncppSrc == 3){
      console.warn("From RGB Image2D to RGBA canvas, not sure of this implementation.");
      var destCounter = 0;
      originalImageDataArray.forEach( function(value, index){
        // adding the Alpha chanel
        if( index%4 == 3){
          canvasImageDataArray[destCounter] = 255;
          destCounter++;
        }

        // regular RGB
        canvasImageDataArray[destCounter] = that._stretchMinMax(value);
        destCounter ++;
      });
    }

    this._ctx.putImageData(canvasImageData, 0, 0);

  }


  /**
  * [PRIVATE]
  * remap the intensity between getMetadata("min") and getMetadata("max")
  * @param {Number} intensity - input pixel value
  * @return {Number} the adjusted number
  */
  _stretchMinMax( intensity ){
    var min = this.getMetadata("min");
    var max = this.getMetadata("max");

    if(min == 0 && max == 255){
      return intensity;
    }

    return ( (intensity - min) / (max - min) ) * 255;
  }

}

export { CanvasImageWriter }

@@ -1424,16 +1424,53 @@
 , 255);%0A
+    this.setMetadata(%22reset%22, true);%0A
 %0A%0A    //
@@ -1709,16 +1709,125 @@
 ID%22) );%0A
+%0A    if(! parentElem )%7B%0A      return false;%0A    %7D%0A%0A    // reset content%0A    if(this.getMetadata(%22reset%22))%7B%0A  
     whil
@@ -1854,16 +1854,18 @@
 hild) %7B%0A
+  
         
@@ -1911,16 +1911,24 @@
 Child);%0A
+      %7D%0A
     %7D%0A%0A 
@@ -2514,16 +2514,34 @@
 canvas);
+%0A%0A    return true;
 %0A  %7D%0A%0A%0A 
@@ -3192,24 +3192,29 @@
  canvas%0A    
+if( !
 this._init()
@@ -3213,17 +3213,114 @@
 ._init()
-;
+ )%7B%0A      console.warn(%22The parent div was not specified or does not exist.%22);%0A      return;%0A    %7D
 %0A    var

ADD reseting the parent is now an option