/**
 * GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
 * *
 * Copyright (C) 2011, 2012 Loic J. Duros
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see  <http://www.gnu.org/licenses/>.
 *
 */

// node.js url module. Makes it easier to resole 
// urls in that datauri loaded dom
var urlHandler = require("url_handler/url_handler");
var {Cc, Ci, Cu, Cm, Cr} = require("chrome");

var data = require("sdk/self").data;

// license definitions, we are using canonical urls and license
// identifiers.
var licenses = require('js_checker/license_definitions').licenses;

var getLicenseList = require('html_script_finder/web_labels/find_js_labels').getLicenseList;
const types = require("js_checker/constant_types");

const addToCache = require("html_script_finder/web_labels/script_hash_worker").addToCache;

// keep web labels in memory so that they can be checked even when they
// are embedded dynamically.
var jsWebLabelEntries = {};

// store the url to js web labels already visited during this session
var jsLabelsPageVisited = {}; 

var webLabelFinder = {

  dom: null,
  pageURL: null,
  jslicenseURL: null,
  pageContent: null,
  licenseList:null,
  callback: null,
  
  init: function (dom, pageURL, callback) {
	  this.pageURL = pageURL;
	  this.dom = dom;
	  this.callback = function () { 
      // rewrite callback as soon as it is triggered once.
      this.callback = function () { 
        //console.log("Callback already called");
      };
      callback();
    };
	  this.findJavaScriptLicenses();
	  this.pageContent = '';
	  this.jslicenseURL = '';
  },

  findJavaScriptLicenses: function () {
	  
	  this.searchForJsLink();

	  if (this.jslicenseURL && !(jsLabelsPageVisited[this.jslicenseURL])) {
	    // get content from license page.
	    this.pageContent = this.fetchLicensePage();
	  }
    else {
      //console.log(this.jslicenseURL, "already visited");
      this.callback();
    }
	  
  },

  searchForJsLink: function () {
	  //console.log('triggered searchForJsLink');
	  var linkTags = this.dom.getElementsByTagName('a'),
	      i = 0,
	      len = linkTags.length,
	      path;

	  // loop through all a tags.
	  for (; i < len; i++) {
	    if (linkTags[i].hasAttribute('rel') &&
	        linkTags[i].getAttribute('rel') === 'jslicense') {

        return this.formatURL(linkTags[i]);
	    }
	  }
	  // no js web labels were found. call back.
	  this.callback();
  },

  formatURL: function (link) {
	  this.jslicenseURL = urlHandler.resolve(this.pageURL, link.href);
	  this.jslicenseURL = urlHandler.addFragment(this.jslicenseURL, 'librejs=true');
	  //console.log('license URL found', this.jslicenseURL);
  },
  
  fetchLicensePage: function () {
	  var that = this;
    try {

      var req =  Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();

      req.onload = function() {
        //console.log("URL is ", this._url);
        that.licenseList = getLicenseList(this.responseXML);
        that.matchListWithDefs(this._url);

		    // add these entries to the global
		    // object for dynamically embedded scripts.
		    jsWebLabelEntries[that.pageURL] = that.licenseList;
        jsLabelsPageVisited[req._url] = 1;
		    // return array to requester object
		    that.callback(that.licenseList);

        
      };

      req.open('GET', this.jslicenseURL, true);
      req._url = this.jslicenseURL;
      req.responseType = "document";
      req.send();

    } catch (e) {
      console.log(e, e.lineNumber, e.fileName, this.jslicenseURL);
      this.callback({});
    }

  },
  matchListWithDefs: function (jslicenseURL) {
	  var i = 0, 
	      len = this.licenseList.length,
	      lic,
	      licDef,
        urlLength,
        iUrl, 
        licArray = null, 
        license, script;

	  // nested loop.
	  for (; i < len; i++) {

	    lic = this.licenseList[i];
      var that = this;
	    for (license in licenses) {

		    licDef = licenses[license];
        if (licDef.canonicalUrl != undefined) {
          if (typeof licDef.canonicalUrl == 'string') {
            // this is a string. make it an array.
            licArray = [licDef.canonicalUrl];
          }  else {
            licArray = licDef.canonicalUrl;
          }

          urlLength = licArray.length;
          for (iUrl = 0; iUrl < urlLength; iUrl++) {
            if (urlHandler.removeFragment(licArray[iUrl]) === urlHandler.removeFragment(lic.licenseUrl)) {
		          lic.free = true;
              // call write function async.
              //console.log("Calling addToCache");
              // timers.setTimeout(function () { addToCache(lic); }, 5);
              // making it initially synchronous.
              var notif = require("ui/notification").createNotification(lic.fileUrl).notification;
              addToCache(lic, 0, jslicenseURL);
		          break;
		        }
          }
        }


	    }

	  }

  }
};

exports.webLabelFinder = webLabelFinder;

// store the web labels harvested across webpages (single session).
exports.jsWebLabelEntries = jsWebLabelEntries;
