/*
 * Copyright (c) OutWit Technologies 2007-2017.
 * All rights reserved.
 */

/**
 * Manipulate the pixel data of an image to set the ui accordingly to
 * the user desires.
 *
 * @author 21
 * @name ImageColor
 * @version 0.2
 *
 */


/**
 *
 * Skin manager is a simple class to change the Hue of an
 * image.
 * Theorically you can change all the whole set of HSV if you
 * need it but for us we just change H.
 *
 * The service is waiting for the URL of an image, a HSV to apply
 * and a callback function.
 *
 *
 * XXX Mix this with the EffectManager, and then move to kernel
 *
 */


var inStock = [];


var ImageColor = {
  canvas:null,
  _isinit:false,
  initialize:function(){
    for(var i = 0 ; i< this._skinElements.length ; i++){
      var img = document.createElementNS("http://www.w3.org/1999/xhtml", "html:img");
      img.setAttribute("src",this._skinElements[i]);
      this.computed.push(img);
      if(!this.canvas)
        this.canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "html:canvas");
    }
    this.applySkin(ow.app.kernel.prefs.getInt("oWImages.hue", 50), ow.app.kernel.prefs.getInt("oWImages.transparency", 150));
  },

  _skinElements:[
      "chrome://outwit-modules-images/skin/oW-images-halo.png",
      "chrome://outwit-modules-images/skin/oW-images-menuHalo.png",
      "chrome://outwit-modules-images/skin/oW-images-catchHalo.png",
      "chrome://outwit-modules-images/skin/oW-images-button-classic.png",
      "chrome://outwit-modules-images/skin/scrollbar/oW-images-rail.png",
      "chrome://outwit-modules-images/skin/oW-images-cursor.png",
      "chrome://outwit-modules-images/skin/oW-images-buttonHalo.png",
      "chrome://outwit-modules-images/skin/oW-images-button-classic-small.png",
      "chrome://outwit-modules-images/skin/oW-images-slideshowButton.png",
      "chrome://outwit-modules-images/skin/oW-images-ref.png"
  ],
  computed:[],
  applySkin: function( aHue, aValue ){
      var isComplete = true;
      for(var i = 0 ; i < this.computed.length ; i++){
        if(!this.computed[i].complete){
          isComplete = false;
          break;
        }
      }
      if( !isComplete ){
        coreKit.timerService.setTimer(100, null, ImageColor.applySkin, ImageColor, aHue, aValue);
        return;
      }
      this.skinElements = [];
      // halo
      this.skinElements.push({src:this.computed[0], width:this.computed[0].naturalWidth, height:this.computed[0].naturalHeight, func:function( src ){
        var target = document.getElementById("owImagesContainer").thumbWindow.document.getElementById("mouseHalo");
        target.setAttribute("src",src);
        inStock[0] = src;
      }});

      //menu halo
      this.skinElements.push({src:this.computed[1], width:this.computed[1].naturalWidth, height:this.computed[1].naturalHeight, func:function( src ){
        var target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule(".owImagesBottomMenuButton:hover { background-image:url(" + src + ") !important}", target.cssRules.length);
      }});
      this.skinElements.push({src:this.computed[1], width:this.computed[1].naturalWidth, height:this.computed[1].naturalHeight, func:function( src ){
        var target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule(".owImagesBottomMenuSwitchButton:hover { background-image:url(" + src + ") !important}", target.cssRules.length);
        inStock[1] = src;
      }});

      //catch halo
      this.skinElements.push({src:this.computed[2], width:this.computed[2].naturalWidth, height:this.computed[2].naturalHeight, func:function( src ){
        var target = document.getElementById("owImagesContainer").thumbWindow.document.getElementById("catchHalo");
        target.src = src;
        inStock[2] = src;
      }});

      this.skinElements.push({src:this.computed[3], width:this.computed[3].naturalWidth, height:this.computed[3].naturalHeight, func:function( src ){
        target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule("#owImagesMediaCatchNavLeft { list-style-image:url(" + src + ") !important}", target.cssRules.length);
        target.insertRule("#owImagesMediaCatchNavRight { list-style-image:url(" + src + ") !important}", target.cssRules.length);
        inStock[3] = src;
      }});
      
      this.skinElements.push({src:this.computed[4], width:this.computed[4].naturalWidth, height:this.computed[4].naturalHeight, func:function( src ){
        var target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule("scrollbar[orient=horizontal] > slider {background-image: url(" + src + ") !important;}", target.cssRules.length);
        var target = document.getElementById("owImagesContainer").thumbWindow.document.getElementById("imageViewProgressRail");
        target.setAttribute("src",src);
        inStock[4] = src;
      }});
      this.skinElements.push({src:this.computed[5], width:this.computed[5].naturalWidth, height:this.computed[5].naturalHeight, func:function( src ){
        var target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule("slider > thumb[orient=horizontal] > box[anonid=thumbmiddle] > image {list-style-image: url(" + src + ") !important;}",target.cssRules.length);
        target.insertRule("slider > thumb[orient=horizontal] > box[anonid=thumbleft] > image{ list-style-image: url(" + src + ") !important;}",target.cssRules.length);
        target.insertRule("slider > thumb[orient=horizontal] > box[anonid=thumbright] > image { list-style-image: url(" + src + ") !important;}",target.cssRules.length);
        target = document.getElementById("owImagesContainer").thumbWindow.document.getElementById("imageViewProgressLine");
        target.style.listStyleImage = 'url(' + src + ') !important;';
        target = document.getElementById("owImagesContainer").thumbWindow.document.getElementById("imageViewProgressEnd");
        target.style.listStyleImage = 'url(' + src + ') !important;';
        inStock[5] = src;
      }});

      // right buttons halo
      this.skinElements.push({src:this.computed[6], width:this.computed[6].naturalWidth, height:this.computed[6].naturalHeight, func:function( src ){
        var target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule(".owImagesCatchButton:hover { background-image:url(" + src + ") !important}", target.cssRules.length);
        inStock[6] = src;
      }});

      //nav buttons
      this.skinElements.push({src:this.computed[7], width:this.computed[7].naturalWidth, height:this.computed[7].naturalHeight, func:function( src ){
        var target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule("#nav-button-back{ list-style-image:url(" + src + ") !important}", target.cssRules.length);
        target.insertRule("#nav-button-next{ list-style-image:url(" + src + ") !important}", target.cssRules.length);
        inStock[7] = src;
      }});
      this.skinElements.push({src:this.computed[8], width:this.computed[8].naturalWidth, height:this.computed[8].naturalHeight, func:function( src ){
        var target = document.styleSheets[document.styleSheets.length-1];
        target.insertRule("#nav-button-slideshow{ list-style-image:url(" + src + ") !important}", target.cssRules.length);
        inStock[8] = src;
      }});


      this.skinElements.push({src:this.computed[9], width:this.computed[9].naturalWidth, height:this.computed[9].naturalHeight, func:function( src ){}});
      try{

        if(inStock.length == this.skinElements.length && false){
          var i = 0;
          for( i ; i < this.skinElements.length - 1 ; i++){
            var element = this.skinElements[i];
            element.func( inStock[i] );
          }
          this._applyHue( element.src, aHue, aValue, element.width, element.height, element.func);
        }
        else{
          for( var i = 0 ; i < this.skinElements.length ; i++){
            var element = this.skinElements[i];
            //XXX sorry!!!!
            if( (i <= 3) || (i==7) )
              this._applyHue( element.src, aHue, aValue, element.width, element.height, element.func);
            else
              this._applyHue( element.src, aHue, -1 , element.width, element.height, element.func);  
          }
        }
     
  
      var target = document.getElementById("owImagesContainer").thumbWindow.document.styleSheets[0]; //main.css
      target.insertRule(".diapo:hover {border:1px solid rgb(" + this.rgbhack.red + "," + this.rgbhack.green + "," + this.rgbhack.blue + ") !important;}", target.cssRules.length);
      target = document.styleSheets[document.styleSheets.length-1];
      target.insertRule("#owImagesMenuLine{background: rgb(" + this.rgbhack.red + "," + this.rgbhack.green + "," + this.rgbhack.blue + ") !important;}", target.cssRules.length);
      target.insertRule(".owImagesBottomMenuButton:hover{color: rgb(" + this.rgbhack.red + "," + this.rgbhack.green + "," + this.rgbhack.blue + ") !important;}", target.cssRules.length);
      target.insertRule(".owImagesBottomMenuButton[active=true] { color:rgb(" + this.rgbhack.red + "," + this.rgbhack.green + "," + this.rgbhack.blue + ") !important;}", target.cssRules.length);
      target.insertRule(".owImagesBottomMenuSwitchButton[active=true] { color:rgb(" + this.rgbhack.red + "," + this.rgbhack.green + "," + this.rgbhack.blue + ") !important;}", target.cssRules.length);
      target.insertRule(".owImagesCatchButton:hover{color: rgb(" + this.rgbhack.red + "," + this.rgbhack.green + "," + this.rgbhack.blue + ") !important;}", target.cssRules.length);

  //oki, we've done show the screen if needed
  document.getElementById("owImagesTopPanel").removeAttribute("style"); //seems strange but this is a linux bug.
  document.getElementById("owImagesContainer").removeAttribute("collapsed");
  document.getElementById("owImagesBottomPanel").removeAttribute("collapsed");

  if(!this._isinit){
    coreKit.timerService.setTimer(1500, null, function() {
			document.getElementById("owImagesContainer").thumbnails.load();
			coreKit.timerService.setTimer(500, null, function() {
        if (ow.app.startPage) {
          outwitImages.browserControls.loadURI(ow.app.startPage);
        }
			}, this);
    }, this);
		this._isinit = true;
  }
  }catch(e){
    dump(e);
  }

  }
}



/**
 * Change the hue of a specified image.
 * Be careful this is a extremely slow process,
 */
ImageColor._applyHue = function( anImageUrl, aHue, aValue, width, height, aCallbackFunction ){
    if(!this.canvas)
      this.canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "html:canvas");
    var ctx = this.canvas.getContext("2d");
    this.canvas.setAttribute("width", width);
    this.canvas.setAttribute("height", height);
    try{
      ctx.drawImage(anImageUrl, 0, 0);
      var pixels = [];

      var imgData = ctx.getImageData(0, 0, width, height); 
      var data = imgData.data;
      var newData = [];
      for( var i = 0; i< data.length;){
        var map = data[i] + '-' + data[i+1] + '-' + data[i+2] + "-" + aValue + "-" + aHue;
        if( this.mapping[map] ){
          newData.push(this.mapping[map].r);
          newData.push(this.mapping[map].g);
          newData.push(this.mapping[map].b);
          i+=3;
          newData.push(data[i++]);
        }
        else{
          var hsv = this._RGBtoHSV(data[i++], data[i++], data[i++]);
          var pixel = this._HSVtoRGB(aHue/100, hsv.s, (aValue==-1)?hsv.v:aValue);
          newData.push(pixel.r);
          newData.push(pixel.g);
          newData.push(pixel.b);
          newData.push(data[i++]);
          this.mapping[map] = { r:pixel.r, g:pixel.g, b:pixel.b};
        }
      }
      
      ctx.putImageData({width:width,height:height,data:newData}, 0, 0);
      aCallbackFunction( this.canvas.toDataURL() );
    }catch(e){
      dump(anImageUrl + '::' + e);
    }
}



ImageColor.rgbhack = { red:0, green:0, blue:0 };

ImageColor.mapping = {};

ImageColor._RGBtoHSV = function( red, green, blue ) {
    var max = Math.max(Math.max(red, green), blue);
    var min = Math.min(Math.min(red, green), blue);
    var hue;
    var saturation;
    var value = max;
    if (min == max){
        hue = 0;
        saturation = 0;
    }
    else{
        var delta = (max - min);
        saturation = delta / max;
        if (red == max)
            hue = (green - blue) / delta;
        else if (green == max)
            hue = 2 + ((blue - red) / delta);
        else
            hue = 4 + ((red - green) / delta);

        hue /= 6;
        if (hue < 0)
            hue += 1;

        if (hue > 1)
            hue -= 1;
    }
    return {
        h: hue,
        s: saturation,
        v: value
    };
};

ImageColor._HSVtoRGB = function( hue, saturation, value ){
    var red = 0.0, green = 0.0, blue = 0.0;
    if(value != 0 ){
        var i = Math.floor(hue * 6);
        var f = (hue * 6) - i;
        var p = value * (1 - saturation);
        var q = value * (1 - (saturation * f));
        var t = value * (1 - (saturation * (1 - f)));
        switch (i){
            case 1: red = q; green = value; blue = p; break;
            case 2: red = p; green = value; blue = t; break;
            case 3: red = p; green = q; blue = value; break;
            case 4: red = t; green = p; blue = value; break;
            case 5: red = value; green = p; blue = q; break;
            case 6: // fall through
            case 0: red = value; green = t; blue = p; break;
        }
        this.rgbhack.red = parseInt(red);
        this.rgbhack.blue = parseInt(blue);
        this.rgbhack.green = parseInt(green);
    }
    return {r: red, g: green, b: blue};
};

