/**
 * 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/>.
 *
 */



var licenses = require('js_checker/license_definitions');
var simpleStorage = require("sdk/simple-storage");
const LAZY = licenses.types.LAZY;
var licenseRegex = [];

const types = require("js_checker/constant_types");

const token = types.token;

var patternUtils = require('js_checker/pattern_utils').patternUtils;

var licStartLicEndRe = /@licstartThefollowingistheentirelicensenoticefortheJavaScriptcodeinthis(?:page|file)(.*)?@licendTheaboveistheentirelicensenoticefortheJavaScriptcodeinthis(?:page|file)/mi;
var licenseMagnet = /(?:\/\*|\/\/)?.*@license ?(magnet\:\?xt=urn\:btih\:[0-9A-Za-z]+).*/;
var licenseEndMagnet = /(?:\/\*|\/\/)?@license-end[\s]*(this\.narcissusBugFixLibreJS[\s]*|[\s]*)$/mi;
exports.freeCheck = {
  initLicenses: function (licenses) {

	  for (item in licenses) {
	    this.stripLicenseToRegexp(licenses[item]);
	  }
  },

  /**
   * stripLicenseToRegexp
   *
   * Removes all non-alphanumeric characters except for the 
   * special tokens, and replace the text values that are 
   * hardcoded in license_definitions.js
   *
   */
  stripLicenseToRegexp: function (license) {
	  var i = 0, 
	      max = license.licenseFragments.length, 
	      item;

	  for (; i < max; i++) {
	    item = license.licenseFragments[i];
	    item.regex = patternUtils.removeNonalpha(item.text);

	    if (license.licenseFragments[i].type === LAZY) {

		    // do not permit words before. Since "Not" could be added
		    // and make it nonfree. e.g.: Not licensed under the GPLv3.
		    item.regex = '^(?!.*not).*' + item.regex;

	    }
      
	    item.regex = new RegExp(patternUtils.replaceTokens(item.regex), 'i'); 
	  }

	  return license;
  },

  /**
   * checkNodeFreeLicense
   *
   * Check if the node mentions a free license
   * in one of its comments.
   * 
   */
  checkNodeFreeLicense: function (n, jsCode) {
	  var strippedComment,
        magnetLink,
	      comment = this.getComment(n),
	      list = licenses.licenses,
	      i,
	      max,
	      regex,
	      frag, 
	      matchLicStart, 
        matchMagnet,
        license;

	  if (n.counter === 2 &&
	      n.parent != undefined &&
	      n.parent.type === token.SCRIPT &&
	      comment != undefined && 
	      comment != " ") {
	    strippedComment = patternUtils.removeNonalpha(comment);
	    matchLicStart = strippedComment.match(licStartLicEndRe);
      matchMagnet = comment.match(licenseMagnet);
      //console.log("matchMagnet is", matchMagnet);
	    if (matchLicStart) {
		    strippedComment = matchLicStart[1];
	      for (license in list) {	    
		      frag = list[license].licenseFragments;
		      max = list[license].licenseFragments.length;
		      for (i = 0;i < max; i++) {
			      if (frag[i].regex.test(strippedComment)) {
              
			        return {licenseName: list[license].licenseName,
                      type: types.checkTypes.FREE} ;

			      }
		      }
	      }
	    } 
      else if (matchMagnet) {
        let magnetLinkRe = new RegExp(matchMagnet[1].replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"));
        //console.log("magnetLink is", magnetLinkRe);
        
	      for (license in list) {	    
		      frag = list[license].canonicalUrl;
          //console.log("frag is ", frag);
          if (frag != undefined) {
		        max = list[license].canonicalUrl.length;
            //console.log("max is", max);
		        for (i = 0;i < max; i++) {
              //console.log("current frag is", frag[i]);
			        if (frag[i].match(magnetLinkRe)) {
                //console.log("found a match");
                if (jsCode.match(licenseEndMagnet)) {
                  //console.log('jsCode is', jsCode);

			            return {licenseName: list[license].licenseName,
                          type: types.checkTypes.FREE_SINGLE_ITEM} ;

                }
			        }
		        }
          }
	      }        
      }
      else {
		    return;
	    }

	  }

  },

  /**
   * getComment
   *
   * Grab the comment(s) from the node. Concatenates
   * multiple comments.
   * 
   */
  getComment: function (n) {

	  var i = 0, length, comment = "";

	  if (n.blockComments == undefined || n.blockComments == " ") {
	    return;
	  }

	  length = n.blockComments.length;
	  if (length > 0) {
	    for (; i < length; i++) {
		    comment += n.blockComments[i];
	    }
	  }
	  if (comment == "") {
	    return;
	  }
	  return comment;

  }
  
};

exports.freeCheck.initLicenses(licenses.licenses);