
function calculateWorktopSectionTotals(prefix, alerts)
{
  var i=0;
  var e_length=document.getElementById(prefix+"piece_"+i+"_length");
  var e_width=document.getElementById(prefix+"piece_"+i+"_width");

  var total=new Object();
  total.area=0;
  total.width=0;
  total.length=0;
  total.num_pieces=0;
  total.min_area=0;
  total.max_area=0;
  total.min_length=0;
  total.max_length=0;
  total.min_width=0;
  total.max_width=0;

  while (e_length && e_width)
  {
    l=parseFloat(e_length.value,10);
    w=parseFloat(e_width.value,10);

    if (isNaN(l)) { l=0; }
    if (isNaN(w)) { w=0; }

    if (!(l>0) && (w>0))
    {
      if (alerts)
      {
        window.alert(e_length.title + " is invalid");
        e_length.focus();
        e_length.select();
      }
      return false;
    }
    else if ((l>0) && !(w>0))
    {
      if (alerts)
      {
        window.alert(e_width.title + " is invalid");
        e_length.focus();
        e_length.select();
      }
      return false;
    }
    else if (!(l>0) && !(w>0))
    {
      l=0;
      w=0;
    }
    else if (l < w)
    {
      var tmp=w;
      w=l;
      l=tmp;
    }

    e_length.value=l;
    e_width.value=w;

    total.area+=l*w;
    total.length+=l;
    total.width+=w;
    total.num_pieces++;

    if (!total.min_area || (l*w) < total.min_area) { total.min_area=l*w; }
    if (!total.max_area || (l*w) > total.max_area) { total.max_area=l*w; }
    if (!total.min_length || l < total.min_length) { total.min_length=l; }
    if (!total.max_length || l > total.max_length) { total.max_length=l; }
    if (!total.min_width || w < total.min_width) { total.min_width=w; }
    if (!total.max_width || w > total.max_width) { total.max_width=w; }

    i++;
    e_length=document.getElementById(prefix+"piece_"+i+"_length");
    e_width=document.getElementById(prefix+"piece_"+i+"_width");
  }

  total.area=total.area / 1000000.0;
  if (total.num_pieces>0)
  {
    total.avg_area=total.area / total.num_pieces;
    total.avg_length=total.length / total.num_pieces;
    total.avg_width=total.width / total.num_pieces;
  }
  else
  {
    total.avg_area=0;
    total.avg_length=0;
    total.avg_width=0;
  }

  var e_area=document.getElementById(prefix+"area");
  if (e_area) { e_area.value=total.area; }
  var e_length=document.getElementById(prefix+"length");
  if (e_length) { e_length.value=total.length; }
  var e_width=document.getElementById(prefix+"width");
  if (e_width) { e_width.value=total.width; }
  var e_pieces=document.getElementById(prefix+"pieces");
  if (e_pieces) { e_pieces.value=total.pieces; }

  return total;
}

function calculateMaterialSection(prefix, alerts, section_data)
{
  var e_num_type_groups=document.getElementById(prefix+"num_type_groups");
  var num_type_groups=parseInt(e_num_type_groups.value,10);

  var materials_total=0;

  for (var i=0; i<num_type_groups; i++)
  {
    var group_prefix=prefix+"group_"+i+"_";
    var e_product_name=document.getElementById(group_prefix+"product_name");
    var product_name=e_product_name.options[e_product_name.selectedIndex].value;

    var e_num_thickness_groups=document.getElementById(group_prefix+"num_thickness_groups");
    var num_thickness_groups=parseInt(e_num_thickness_groups.value,10);

    for (var j=0; j<num_thickness_groups; j++)
    {
      var thickness_group_prefix=group_prefix+"thickness_group_"+j+"_";

      var e_option_name=document.getElementById(thickness_group_prefix+"option_name");
      var option_name=get_form_element_value(e_option_name);
      if (!option_name)
      {
        if (alerts)
        {
          window.alert("Couldn't find option name for "+thickness_group_prefix+"option_name");
        }
        return false;
      }

      var totals=calculateWorktopSectionTotals(thickness_group_prefix, alerts);
      var area=totals.area;
      if (area<=0 || !area)
      {
        // HACK: should have an admin option for this
        if (j==0)
        {
          if (alerts)
          {
            window.alert("You need to enter the dimensions of pieces.");
            var e_length=document.getElementById(prefix+"group_"+i+"_thickness_group_0_piece_0_length");
            if (e_length)
            {
              e_length.focus();
              e_length.select();
            }
          }
          return false;
        }
      }

      var pp_m2=parseFloat(section_data[product_name].options[option_name].value)

      if (isNaN(pp_m2) || pp_m2<=0)
      {
        kaylee_debug("pp_m2 isn't right: "+pp_m2
                     +' from section_data["'+product_name+'"].options["'+option_name+'"].value: '
                     +section_data[product_name].options[option_name].value );
      }

      var thickness_group_cost=area * pp_m2;
      //kaylee_debug("thickness_group_cost " +thickness_group_cost);
      materials_total+=thickness_group_cost;
    }
  }

  return materials_total;
}

function calculateSectionTotal(prefix, section_name, alerts, section_data)
{
  var e_num_products=document.getElementById(prefix+"num_products");
  var num_products=parseInt(e_num_products.value);

  var section_total=0;

  if (num_products==0 && alerts)
  {
    if (window.confirm("You have selected no "+section_name+", do you wish to add some? (Click cancel to continue anyway)"))
    {
      return false;
    }
  }

//  for (var i=0; i<num_products; i++)
  for (var i=0; i<=num_products; i++)
  {
    var product_prefix=prefix+"product_"+i+"_";
    var product_price=0;
    //kaylee_debug("getting id "+product_prefix+"product_name")
    var e_product_name=document.getElementById(product_prefix+"product_name");
    if (undefined!=e_product_name && e_product_name.value!="")
    {
    var product_name=e_product_name.value;


        var e_product_measurement=document.getElementById(product_prefix+"measurement");
        if (e_product_measurement)
        {
          var product_measurement=parseFloat(e_product_measurement.value);
          for (option_name in section_data[product_name].options)
          {
            var option_value=parseFloat(section_data[product_name].options[option_name].value);
            //kaylee_debug("section_data["+product_name+"].options["+option_name+"].value: "+option_value);
            if (option_name=='price per millimetre')
            {
              product_price += option_value * product_measurement;
            }
            else if (option_name=='price per metre')
            {
              product_price += option_value * product_measurement / 1000.0;
            }
            //kaylee_debug(section_name+" product_price now: "+product_price);
          }
        }
    
        var product_quantity=1;
        var e_product_quantity=document.getElementById(product_prefix+"quantity");
        if (e_product_quantity)
        {
          var product_quantity=parseInt(e_product_quantity.value);
          product_price+=parseFloat(section_data[product_name].price);
          product_price=product_quantity * product_price;
          //kaylee_debug("product_price=product_quantity * product_price => " + product_quantity + "*" + product_price + " => product_price: " + product_price);
        }
    
        section_total+=product_price;
        //kaylee_debug("section_total now "+section_total);
    }
  }

  return section_total;
}

function calculateServiceSectionTotal(prefix, totals, alerts, section_data)
{
  var e_num_products=document.getElementById(prefix+"num_products");
  var num_products=parseInt(e_num_products.value);

  var section_total=0;

  for (var i=0; i<num_products; i++)
  {
    var product_prefix=prefix+"product_"+i+"_";
    var product_price=0;
    //kaylee_debug("getting id "+product_prefix+"product_name")
    var e_product_name=document.getElementById(product_prefix+"product_name");
    var product_name=e_product_name.value;

    var e_product_enabled=document.getElementById(product_prefix+"enabled");
    if (e_product_enabled && e_product_enabled.checked)
    {
      var product_catalog_price = parseFloat(section_data[product_name].price);
      if (!isNaN(product_catalog_price) && product_catalog_price>0)
      {
        product_price += product_catalog_price;
      }
    
      for (option_name in section_data[product_name].options)
      {
        var option=section_data[product_name].options[option_name];
        var option_value=parseFloat(option.value);
        var option_min_price=parseFloat(option.min_price);

        var quote_option_price=0;

        var re_res;
        
        var re_piece_aggregate=new RegExp('(sum|average|max|min|count) worktop piece(s| area| length| width)( per sq m| per millimetre| per metre)?','i');

        //kaylee_debug("section_data["+product_name+"].options["+option_name+"].value: "+option_value);
        if (re_res=re_piece_aggregate.exec(option_name))
        {
          if (isNaN(option_value)) { continue; }

          var total_property_prefix='';
          switch (re_res[1])
          {
            case 'average': case 'Average': total_property_prefix='avg_'; break;
            case 'max': case 'Max': total_property_prefix='max_'; break;
            case 'min': case 'Min': total_property_prefix='min_'; break;
            case 'sum': case 'Sum':
              break;
            default:
              kaylee_debug("unhandled option aggregator: "+option_name);
              break;
          }
          var total_property;
          switch (re_res[2])
          {
            case 's': total_property='num_pieces'; break;
            case ' area': case ' Area': total_property=total_property_prefix+'area'; break;
            case ' length': case ' Length': total_property=total_property_prefix+'length'; break;
            case ' width': case ' Width': total_property=total_property_prefix+'width'; break;
            default:
              kaylee_debug("unhandled option dimension: "+option_name);
              break;
          }

          var param_value=totals[total_property];

          if (re_res[3]==' per metre') { param_value = param_value / 1000.0; }

          if (option.min_value && !isNaN(option.min_value) && param_value<option.min_value)
          { param_value=option.min_value; }

          quote_option_price += option_value * param_value;
          //kaylee_debug(product_name+" "+option_name+" quote_option_price += "+option_value+"*"+param_value+"="+(option_value*param_value));
        }
        /*
        else if (option_name=='price per millimetre')
        {
          if (isNaN(option_value)) { continue; }

          var param_value = totals.length;

          if (option.min_value && !isNaN(option.min_value) && param_value<option.min_value)
          { param_value=option.min_value; }

          quote_option_price += option_value * param_value;
          kaylee_debug(product_name+" "+option_name+" quote_option_price += "+option_value+"*"+param_value+"="+(option_value*param_value));
        }
        else if (option_name=='price per metre')
        {
          if (isNaN(option_value)) { continue; }

          var param_value = totals.length / 1000.0;

          if (option.min_value && !isNaN(option.min_value) && param_value<option.min_value)
          { param_value=option.min_value; }

          quote_option_price += option_value * param_value;
          kaylee_debug(product_name+" "+option_name+" quote_option_price += "+option_value+"*"+param_value+"="+(option_value*param_value));
        }
        */
        else if (option_name=='distance to closest office in miles') /* || option_name=='price per mile') */
        {
          if (isNaN(option_value)) { continue; }
          var e_distance=document.getElementById(prefix+"distance_miles");
          var e_postcode=document.getElementById(prefix+"postcode");
          var distance=parseFloat(e_distance.value);
          if (isNaN(distance)) 
          {
            if (e_postcode.value)
            {
              //kaylee_debug("would submit here, need to calculate postcode distance.");
              //kaylee_debug("e_distance: " + e_distance);
              //kaylee_debug("distance: " + distance);
              if (alerts) // hacky - but alerts is only set when not submitting
              {
                e_distance.form.submit();
                return false;
              }
            }
            else
            {
              if (alerts)
              {
                e_postcode.focus();
                window.alert("Please enter a postcode so I can calculate delivery costs.");
              }
              return false;
            }
           
            if (alerts)
            {
              window.alert("Unable to calculate service cost because I was unable to calculate the distance between the customer and the company.");
            }
            return false; 
          }
          //kaylee_debug(product_name+" "+option_name+" quote_option_price += "+option_value+"*"+distance+"="+(option_value*distance));

          if (option.min_value && !isNaN(option.min_value) && distance<option.min_value)
          {
            distance=option.min_value;
          }
          quote_option_price += option_value * distance;
        }
        else if (option_name=='special zone charge')
        {
          var e_postcode=document.getElementById(prefix+"postcode");

          if (!check_postcode(e_postcode)) { return false; }

          var customer_postcode=new String(e_postcode.value);
          while (customer_postcode.indexOf(" ")==0)
          {
            customer_postcode=customer_postcode.substr(1);
          }
          while (customer_postcode.lastIndexOf(" ")==(customer_postcode.length-1))
          {
            customer_postcode=customer_postcode.substr(0,customer_postcode.length-1);
          }
          var customer_postcode_parts=e_postcode.value.split(" ");

          var re_areadistrict=new RegExp("^([A-Za-z]+)(.*)");
          customer_areadistrict=re_areadistrict.exec(customer_postcode_parts[0]);
          //kaylee_debug("got customer area district: "+customer_areadistrict.toJSON());

          var option_added=false;
          for (var j=0; j<option.value_list_length && !option_added; j++)
          {
            //kaylee_debug("Considering "+option.value_list_values[j].toJSON());
            if (option.value_list_values[j].enabled)
            {
              var postcodes=option.value_list_values[j].label.split(",");
              for (var k=0; k<postcodes.length && !option_added; k++)
              {
                //robertas var postcode_parts=postcodes[k].split(" ");
                var postcode_parts1=postcodes[k].replace(/^\s+|\s+$/g,"");
                
                var areadistrict=re_areadistrict.exec(postcode_parts1); //1
                //kaylee_debug("postcode_parts[1]:"+postcode_parts[1].toJSON());
                //kaylee_debug("areadistrict:"+areadistrict.toJSON());
                //kaylee_debug("customer_postcode_parts:"+customer_postcode_parts.toJSON());
                //kaylee_debug("customer_areadistrict:"+customer_areadistrict.toJSON());
                if ((areadistrict[2] && postcode_parts1==customer_postcode_parts[0]) //1
                    || (!areadistrict[2] && areadistrict[1]==customer_areadistrict[1]))
                {
                  quote_option_price += option.value_list_values[j].value;
                  option_added=true;
                  //kaylee_debug("Added: "+option.value_list_values[j].toJSON());
                  break;
                }
              }
            }
          }
        }
        else
        {
          //kaylee_debug("Unhanded option for service " + product_name +": "+ option_name + " = " + option.toJSON());
        }
        
        product_price += quote_option_price;
        //kaylee_debug("Services product_price now: "+product_price);
      }
    }

    section_total += product_price;
    
    setIdTextContent(prefix+'product_'+i+'_price',format_money(product_price));

    //kaylee_debug("section_total now "+section_total);
  }

  return section_total;
}

function clearServiceTotals(prefix)
{
  var e_num_products=document.getElementById(prefix+"num_products");
  //kaylee_debug(prefix+"num_products is "+e_num_products);
  var num_products=parseInt(e_num_products.value);

  for (var i=0; i<num_products; i++)
  {
    setIdTextContent(prefix+'product_'+i+'_price',"");
  }
}

function clearTotals(prefix)
{
  clearServiceTotals(prefix+"section_3_");
  setIdTextContent(prefix+"total_cost","");
  setIdTextContent(prefix+"material_cost","");
  var e_num_taxes=document.getElementById(prefix+"num_taxes");
  if (e_num_taxes)
  {
    var num_taxes=parseInt(e_num_taxes.value);
    for (var i=0; i<num_taxes; ++i)
    {
      setIdTextContent(prefix+"tax_"+i+"_value", "");
    }
  }
  setIdTextContent(prefix+"total_cost_inc_taxes","");

  var e_action=document.getElementById("action");
  if (e_action)
  {
    e_action.value="reload";
  }

}

function calculateQuote(prefix, quote_data, alerts)
{
  clearTotals(prefix);

  var e_action=document.getElementById("action");
  if (e_action)
  {
    e_action.value="calculate";
  }

  var materials_total = 0;
  var services_total = 0;
  for (var i=0; quote_data[i] && quote_data[i].config; i++)
  {
    //kaylee_debug("trying quote_data["+i+"].config.type: "+quote_data[i].config.type);
    switch (quote_data[i].config.type)
    {
      case 'Materials':
        var sec_total = calculateMaterialSection(prefix+"section_"+i+"_", alerts, quote_data[i]);
        if (sec_total===false) { return false; }
        if (sec_total) { materials_total += sec_total; }
        break;
      case 'Generic':
        var sec_total = calculateSectionTotal(prefix+"section_"+i+"_", quote_data[i].config.title, alerts, quote_data[i]);
        if (sec_total===false) { return false; }
        if (sec_total) { materials_total += sec_total; }
        break;
      case 'Service':
        var totals_for_services = calculateWorktopSectionTotals(prefix+"section_0_group_0_thickness_group_0_", alerts);

        var sec_total = calculateServiceSectionTotal(prefix+"section_"+i+"_", totals_for_services, alerts, quote_data[i]);
        if (sec_total===false) { return false; }
        if (sec_total) { services_total += sec_total; }
        break;
      default:
        kaylee_debug("type "+quote_data[i].config.type+" not found!");
        break;
    }
  }

  setIdTextContent(prefix+"material_cost",format_money(materials_total));

  var total_price = materials_total + services_total;

  setIdTextContent(prefix+"total_cost",format_money(total_price));

  var total_inc_taxes = total_price;

  var e_num_taxes=document.getElementById(prefix+"num_taxes");
  var num_taxes=parseInt(e_num_taxes.value);
  for (var i=0; i<num_taxes; ++i)
  {
    var e_tax_ratio = document.getElementById(prefix+"tax_"+i+"_ratio");
    var tax_ratio = parseFloat(e_tax_ratio.value);
    var tax=tax_ratio * total_price;
    setIdTextContent(prefix+"tax_"+i+"_value", format_money(tax));
    total_inc_taxes += tax;
  }

  setIdTextContent(prefix+"total_cost_inc_taxes",format_money(total_inc_taxes));

  return true;
}

