﻿// Convert the following datastructure:
//
//    postage_rate:{
//        region:[
//            {
//                name:'Norge',
//                weights:{
//                    weight:[
//                        {
//                            name:'  0 - 20g',
//                            title:'A-Prioritert brevpost',
//                            description:'Tidligst fremme 1 dag etter. Brev frankert med frimerke. Kan få sporing, erstatning, kvittering og nytt utleveringssted ved bruk av tilleggstjenester. Leveres i postkassen',
//                            price:'8,-',
//                            link:'http://www.posten.no/Produkter+og+tjenester/Brev+og+frimerker/7936.cms',
//                            call_to_action:'Les mer'
//                        },
//
// to:
//    regions[name] = 
//      weights [
//        poProduct { int weight, string title, string description, float price },
//            :
//        poProduct { int weight, string title, string description, float price },
//      ]


// Price may also have the format:  "250,- + 72,- pr. kg"

// ------------------------------------------------------------------------------------------------
//  class poProduct
// ------------------------------------------------------------------------------------------------

function poProduct()
{
  this.m_too_small   = false;
  this.m_title       = "";
  this.m_name        = "";
  this.m_description = "";
  this.m_link        = "";
  this.m_price       = 0.0;
  this.m_per_kg      = 0.0;
  this.m_weight      = 0.0;
  this.m_applies_to_product_family = null;
} // end poProduct()



var POPRODUCT = poProduct.prototype;

// static methods
poProduct.addFromJSON = function poProduct_addFromJSON(json)
{
  var po = new poProduct();

  po.m_too_small   = false;
  po.m_title       = json.title;
  po.m_description = json.description;
  po.m_name        = json.name;
  po.m_link        = json.link;
  
  var strPrice     = json.price.replace(/,/g, ".").replace(/-/g, "00");
  // strPrice now has the format:  "250.00 + 72.00 pr. kg"
  var price_patt   = " *([0-9\\\.]+) *(\\\+ *([0-9\\\.]+) pr\\\. kg)?";
  var price_re     = new RegExp(price_patt);
  price_re.exec(strPrice);
  po.m_price       = parseFloat(RegExp.$1);
  po.m_per_kg      = RegExp.$2 ? parseFloat(RegExp.$3) : 0.0;
  
  var patt = " *[0-9]+ *- *([0-9]+) *(k?g) *";
  var re = new RegExp(patt);
  re.exec(json.name);
  po.m_weight = parseFloat(RegExp.$1);
  var unit = RegExp.$2;
  if (unit == "kg")
    po.m_weight *= 1000;
    
  var size_patt = " *([0-9\\\.]+)x([0-9\\\.]+)x([0-9\\\.]+)"; // LxBxH
  var size_re   = new RegExp(size_patt);
  if (size_re.exec(json.description) && RegExp.$1 && RegExp.$2 && RegExp.$3)
  {
    // 43x31xH
    if (RegExp.$1 < 43 || RegExp.$2 < 31)
      po.m_too_small = true;
  }
  po.m_applies_to_product_family = [1, 2, 3, 4, 6];

  return po;  
} // end addFromJSON()


poProduct.add = function poProduct_add(title, name, description, link, base_price, extra_per_kg, max_weight, product_families)
{
  var po = new poProduct();
  po.m_too_small   = false;
  po.m_title       = title;
  po.m_name        = name;
  po.m_description = description;
  po.m_link        = link;
  po.m_price       = base_price;
  po.m_per_kg      = extra_per_kg;
  po.m_weight      = max_weight;
  po.m_applies_to_product_family = product_families;
  return po;
} // end add()



POPRODUCT.getPrice = function poProduct_getPrice(weight_in_grammes)
{
  return this.m_price + this.m_per_kg * Math.ceil(weight_in_grammes / 1000.0);
}; // end getPrice()



POPRODUCT.getPriceDescription = function poProduct_getPriceDescription(weight_in_grammes)
{
  var s = "Kr. " + this.m_price;
  if (this.m_per_kg)
    s += " + " + this.m_per_kg + " pr kg.";
  return s;
}; // end getPriceDescription()



POPRODUCT.getDescription = function poProduct_getDescription()
{
  var s = this.m_name + ". " + this.m_description;
  if (this.m_link)
  {
    var link = "<a href='" + this.m_link + "' target='_blank'>her for mer informasjon</a>";
    if (s.indexOf("les mer") > 0)
      s = s.replace("les mer", link);
    else
      s = s + " Se " + link;
  }
  return s;
}; // end getDescription()



// ------------------------------------------------------------------------------------------------
//  class gtPriceCalculator
// ------------------------------------------------------------------------------------------------

function gtPriceCalculator(shopping_cart, distributor)
{
  this.m_shopping_cart = shopping_cart;
  switch (distributor)
  {
    case gtPriceCalculator.SENTRALDITRIBUSJON:  this.loadFromPostOffice(); break;
    case gtPriceCalculator.KARTAGENA:           this.initkartagena();      break;
    default:  alert("gtPriceCalculator: unknown distributor: " + distributor);
  }
} // end gtPriceCalculator()

var GTPRICECALCULATOR = gtPriceCalculator.prototype;



gtPriceCalculator.SENTRALDITRIBUSJON = 0;
gtPriceCalculator.KARTAGENA          = 1;



GTPRICECALCULATOR.loadFromPostOffice = function gtPriceCalculator_loadFromPostOffice()
{
  var folders = window.location.pathname.split("/");
  var url = window.location.protocol + "//" + window.location.hostname + "/" + folders[1] + "/WebServices/Util.asmx/GetPostageJSON";
  var ajax = new gtAjax(
    url,                                    // sUrl
    function onResult(ajax, xml_dom, text)  // callback
    {
      // Cannot use the parsed XML on Firefox, so we pick out the data manually:
      //   var data = xml_dom.firstChild.nextSibling ? xml_dom.firstChild.nextSibling.nodeTypedValue : xml_dom.firstChild.firstChild.nodeValue; // Handle IE/Firefox
      var start = text.indexOf("{");
      var stop  = text.lastIndexOf("}") + 1;
      var data  = text.substring(start, stop);
      this.m_postage = eval("(" + data + ")");
      var regionCount = this.m_postage.postage_rate.region.length;
      this.m_regions = [];
      for (var r = 0; r < regionCount; r++)
      {
        this.m_regions[r] = [];
        var weightCount = this.m_postage.postage_rate.region[r].weights.weight.length;
        for (var w = 0; w < weightCount; w++)
          this.m_regions[r][w] = poProduct.addFromJSON(this.m_postage.postage_rate.region[r].weights.weight[w]);

      }

      this.m_shopping_cart.m_loaded = true;
      this.m_shopping_cart.m_evt_loaded.raise();
    },
    this,                                   // me (will be the this-pointer inside the callback)
    null,                                   // user_data
    "force-post");                          // post_data (gtAjax issues a POST request if any data is given for this parameter)
  this.m_packaging_weight = 0.0;
}; // end loadFromPostOffice()



GTPRICECALCULATOR.initkartagena = function gtPriceCalculator_initkartagena()
{
  var regionCount = 3;
  this.m_regions = [];
  var region_prices = [26 + 16, 41 + 16, 70 + 16];
  for (var r = 0; r < regionCount; r++)
  {
    this.m_regions[r] = [];

    // Add our local pacaging options for single maps
    this.m_regions[r][0] = poProduct.add(
      "Papprør",                                      // title
      "Papprør med plass til opp til tre enkletkart", // name
      "Sendes direkte fra Kartagena",                 // description
      "",   // link
      region_prices[r], // base_price,
      0.0,  // extra_per_kg,
      60.0, // max_weight,
      [5]
    );
  }
  this.m_packaging_weight = 290.0;
}; // end initkartagena()



function findProductOfWeight(weights, grammes)
{
  for (var w = 0; w < weights.length; w++)
  {
    if (weights[w].m_too_small)
      continue;
      
    if (weights[w].m_weight >= grammes)
      return weights[w];
  }
  return null;
} // end findProductOfWeight()



GTPRICECALCULATOR.calcPriceFromWeightInG = function gtPriceCalculation_calcPriceFromWeightInG(grammes, region)
{
  if (grammes == 0)
    return 0;
    
  var weights = this.m_regions[region];
  var largest = weights[weights.length - 1];
  var collies = Math.ceil(grammes / largest.m_weight);
  var price   = 0;
  
  for (var c = 0; c < collies - 1; c++)
  {
    price   += largest.getPrice(largest.m_weight);
    grammes -= largest.m_weight;
  }

  var prod = findProductOfWeight(weights, grammes);
  price += (prod ? prod.getPrice(grammes) : 0);
    
  return Math.ceil(price);
}; // end calcPriceFromWeightInG()



GTPRICECALCULATOR.renderExplanation = function gtPriceCalculation_renderExplanation(grammes, region)
{
  var s =
    "<table class='gtExplanation' cellspacing='0'>\n" +
    "<tr>\n" +
    "<th class='gtExplanationHeader'>" + "Antall" + "</th>" +
    "<th class='gtExplanationHeader'>" + "Pris pr stk" + "</th>" +
    "<th class='gtExplanationHeader'>" + "Type" + "</th>" +
    "<th class='gtExplanationHeader'>" + "Vekt" + "</th>" +
    "<th class='gtExplanationHeader'>" + "Sum" + "</th>" +
    "<th class='gtExplanationHeader'>" + "Beskrivelse" + "</th>\n" +
    "</tr>\n";

  if (grammes > 0)
  {  
    var weights = this.m_regions[region];
    var largest = weights[weights.length - 1];
    var collies = Math.floor(grammes / largest.m_weight);
    var price   = largest.getPrice(largest.m_weight);
    if (collies > 0)
    {
      s +=
        "<tr> <td class='gtExplainCount'>" + collies +
        "</td><td class='gtExplainPrice'>" + largest.getPriceDescription(largest.m_weight) +
        "</td><td class='gtExplainType'>" + largest.m_title +
        "</td><td class='gtExplainWeight'>" + (this.m_packaging_weight + largest.m_weight) / 1000 + " kg" +
        "</td><td class='gtExplainSum'>Kr. " + largest.getPrice(largest.m_weight) +
        "</td><td class='gtExplainDescription'>" + largest.getDescription() +
        "</td></tr>";
      grammes -= (collies * largest.m_weight);
    }
    if (grammes > 0)
    {
      var prod = findProductOfWeight(weights, grammes);
      price = (prod ? prod.getPrice(grammes) : 0);
      s +=
        "<tr> <td class='gtExplainCount'>" + 1 +
        "</td><td class='gtExplainPrice'>" + prod.getPriceDescription(prod.m_weight) +
        "</td><td class='gtExplainType'>" + prod.m_title +
        "</td><td class='gtExplainWeight'>" + (this.m_packaging_weight + grammes) / 1000 + " kg" +
        "</td><td class='gtExplainSum'>Kr. " + prod.getPrice(grammes) +
        "</td><td class='gtExplainDescription'>" + prod.getDescription() +
        "</td></tr>";
    }
  }
  
  s += "</table><input type='button' value='Ok' onclick='" + this.m_shopping_cart.m_name_of_variable + ".closeExplanation(this.parentNode);' />";
  return s;
}; // end renderExplanation()
