import("system.vars");
import("system.util");
import("system.datetime");
import("system.text");
import("system.neon");
import("system.db");
import("system.translate");
import("system.eMath");
import("Util_lib");
import("Sql_lib");
import("Keyword_lib");
import("Product_lib");
import("Report_lib");
import("OfferOrder_lib");
import("PostalAddress_lib");

/**
 * Methods used by Offer.
 * Do not create an instance of this!
 * 
 * @class
 */
function OfferUtils() {}
   
/**
 * Delivers the next valid offer number (has to be unique)
 * 
 * @return {String} next valid offer number
 */
OfferUtils.getNextOfferNumber = function() {
    return NumberSequencingUtils.getNextUniqueNumber("OFFERCODE", "OFFER");
}
    
/**
 * Delivers the next valid offer version number
 * 
 * @return {String} offerCode next valid offer version number
 */
OfferUtils.getNextOfferVersionNumber = function(offerCode) {
    return NumberSequencingUtils.getNextUniqueNumber("VERSNR", "OFFER", 1, "OFFERCODE = " + offerCode);
}
    
/**
 * Checks if the passed offer number is valid (has to be unique)
 * 
 * @param {String} offerNumber offer number to check
 * 
 * @return {Boolean} passed number is valid
 */
OfferUtils.validateOfferNumber = function(offerNumber) {
    return NumberSequencingUtils.validateUniqueNumber(offerNumber, "OFFERCODE", "OFFER");
}
    
OfferUtils.getOfferNumberValidationFailString = function() {
    return translate.text("The offer number already exists!");
}
    
OfferUtils.isEditable = function(status) {
    // TODO: Administrator darf immer ändern, warten auf neue Berechtigungslogik?

    // Offer should be editable if offer state not equals "Sent", "Won" or "Lost"
    return status != "2" && status != "3" && status != "4";
}

/**
 * Create a new offer and open the offer context in NEW-mode
 */
OfferUtils.createNewOffer = function(pSalesprojectId, pRelationId)
{
    var params = {};
    
    if (pSalesprojectId)
        params["SalesprojectId_param"] = pSalesprojectId;
    
    if (pRelationId)
        params["RelationId_param"] = pRelationId;
    
    neon.openContext("Offer_context", null, null, neon.OPERATINGSTATE_NEW, params);
}


/*
 * Open Offer report
 * 
 * @param {String} pOfferID
 *
 * @return {[]}
 */
OfferUtils.openOfferReport = function(pOfferID)
{    
    var offerReport = new Report("RPTJ_OFFER");  
    
    // get data from DB
    // TODO: OFFER.ADDRESS
    var fields = [/*"OFFER.ADDRESS"*/ "''", "OFFER.RELATION_ID", "OFFER.LANGUAGE", /*"OFFER.PAYMENTTERMS"*/ "'DUMMY_OFFER.PAYMENTTERMS'", //0 - 3
    /*"OFFER.DELIVERYTERMS"*/ "'DUMMY_OFFER.DELIVERYTERMS'", "OFFER.OFFERCODE", "OFFER.CURRENCY", "OFFER.OFFERDATE", //   4 - 7
    "OFFER.OFFERID", "OFFERITEM.OFFER_ID", "OFFERITEM.INFO", "OFFERITEM.ASSIGNEDTO", // 11
    "OFFERITEM.PRODUCT_ID","OFFERITEM.ITEMNAME" , // 13
    "OFFERITEM.OPTIONAL", "OFFERITEM.ITEMPOSITION", // 15
    "PRODUCT.PRODUCTCODE", "PRODUCT.PRODUCTID", "OFFER.FOOTER", "OFFER.HEADER", "OFFERITEM.UNIT", "OFFER.VAT", // 21
    "COALESCE(OFFERITEM.QUANTITY,0)","COALESCE(OFFERITEM.PRICE,0)", "COALESCE(OFFERITEM.DISCOUNT,0)", // 24
    "COALESCE(OFFER.VERSNR, 0)", "COALESCE(OFFER.OFFERCODE,0)", "COALESCE(OFFERITEM.VAT, 0)", "0", "''", "SALESPROJECT_ID" ]; // 30
    
    var offerFromSql = " from PRODUCT" 
                     + " inner join OFFERITEM on (PRODUCT.PRODUCTID = OFFERITEM.PRODUCT_ID) "
                     + " inner join OFFER on (OFFERITEM.OFFER_ID = OFFER.OFFERID)";
   
    var offerCondition = SqlCondition.begin().andPrepare("OFFER.OFFERID", pOfferID);
    var rptdata = db.table(offerCondition.buildSelect("select " + fields.join(", ") + offerFromSql, "1 = 0"));
    
    var language = KeywordUtils.get("LANGUAGE", rptdata[0][2])[1];
    var relid = rptdata[0][1];
    
    // TODO: AddrObject implementieren
    //var addrobj = new AddrObject(relid);
    
    // new logik: Relationid from Org is always also the OrgId
    var orgrelid = relid;
    
    var fullPrice= 0;
    var itemSum = 0;
    var sumItemSum = 0;
    var total = 0;
    var sums = [];
    var vatsum = 0;
    
    // discount-condtion = offerCondition + additional condition. So we can reuse the previous object
    offerCondition.andPrepare("OFFERITEM.DISCOUNT", 0, "# <> ?");
    
    var countDiscounts = db.cell(SqlCondition.begin()
                                             .andPrepare("OFFER.OFFERID", pOfferID)
                                             .buildSelect("select count(OFFERITEM.DISCOUNT)" + offerFromSql, "1 = 0"));


    for(var i = 0; i < rptdata.length; i++)
    {                
        var optional = rptdata[i][14];
        
        // calculate:
        // "OFFERITEM_QUANTITY" * "OFFERITEM_PRICE"
        fullPrice = eMath.mulDec(parseFloat(rptdata[i][22]), parseFloat(rptdata[i][23]) );

        // ( fullPrice * ( 100 - "OFFERITEM_DISCOUNT" ) ) / 100
        if(optional)
        {
            itemSum = eMath.roundDec(eMath.divDec(eMath.mulDec(fullPrice, eMath.subDec(100, rptdata[i][24]) ), 100), 2, eMath.ROUND_HALF_EVEN); //Summe je Artikel
            sumItemSum += itemSum; //Gesamtsumme aller Artikel      
        }
        // itemSum * "OFFERITEM_VAT" / 100
        vatsum = (eMath.divDec(eMath.mulDec(itemSum, rptdata[i][27] ), 100)); //Steuerbetrag in Euro je Artikel
        if(rptdata[i][27] > 0) sums.push([rptdata[i][27], vatsum]); //MWSteuerwerte für Map vorbereiten
        // sumItemSum + "OFFER_VAT"
        total = eMath.addDec(sumItemSum, rptdata[i][21]); //Gesamtsumme zzgl. MwSt.
        total = text.formatDouble(total, translate.text("#,##0.00"), true)
        // format date
        rptdata[i][7] = datetime.toDate(rptdata[i][7], translate.text("dd.MM.yyyy", language));
        // format numbers
        rptdata[i][23] = text.formatDouble(rptdata[i][23], translate.text("#,##0.00"), true);
        rptdata[i][24] = text.formatDouble(rptdata[i][24], translate.text("0.00"), true);
        rptdata[i][22] = text.formatDouble(rptdata[i][22], translate.text("#,##0"), true);
        rptdata[i][27] = text.formatDouble(rptdata[i][27], translate.text("#,##0.00"), true);
        rptdata[i][28] = text.formatDouble(itemSum, translate.text("#,##0.00"), true); //Immer zwei Nachkommastellen und ',' statt '.' 
        rptdata[i][29] = KeywordUtils.get("UNIT", rptdata[i][20])[1];
    }
    
    // TODO: get Images implementieren
    var imgData = ["meineFirma | Konrad-Zuse-Straße 4  |  DE 84144 Geisenhausen",
                   "base64:iVBORw0KGgoAAAANSUhEUgAAAM4AAABRCAYAAACaL5lSAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDA4QzAyM0IwREIwMTFFNEFGMDREM0VEMjExRjlBRTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDA4QzAyM0MwREIwMTFFNEFGMDREM0VEMjExRjlBRTIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMDhDMDIzOTBEQjAxMUU0QUYwNEQzRUQyMTFGOUFFMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMDhDMDIzQTBEQjAxMUU0QUYwNEQzRUQyMTFGOUFFMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhF3nYoAAAlvSURBVHja7J1fjBXV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"]
                // getMyASYS_ICONSdata();
    
    var params = {};
    params["myAddr"] = imgData[0];
    params["Pos"] = translate.text("Pos.", language);
    params["Artikelbezeichnung"] = translate.text("Artikelbezeichnung", language);
    params["Artikel-Nr"] = translate.text("Artikel-Nr", language);
    params["Einzelpreis"] = translate.text("Einzelpreis", language);
    params["Menge"] = translate.text("Menge", language);
    params["UMSt"] = translate.text("UMSt", language);
    params["Datum"] = 	translate.text("Datum", language);
    params["Nummer"] = translate.text("Nummer", language);
    params["Zahlungsbedingung"] = translate.text("Zahlungsbedingung", language);
    params["Lieferbedingung"] = translate.text("Lieferbedingung", language);
    params["Rabatt"] =  translate.text("Rabatt", language);
    params["Gesamt"] =  translate.text("Gesamt", language);
    params["Summe"] = 	translate.text("Summe", language);
    params["zzglUMST"] = translate.text("zzgl. Summe UmSt", language);
    
    // TODO: OFFER.ADDRESS 
    params["OFFERAddr"] = AddressUtils.getAddress(relid).toString(); //rptdata[0][0];
    // TODO: AddrObject implementieren
    params["OFFERPers"] = (AddressUtils.getLetterSalutation() + ",").toString(); //addrobj.formatAddress("{ls},");
    
    // TODO: payment / delivery-Terms implement (if needed)
    params["OFFERPay"] = ""//getKeyName(rptdata[0][3] , "PAYMENTTERMS", "KEYNAME1", language);
    params["OFFERDel"] = ""//getKeyName(rptdata[0][4] , "DELIVERYTERMS", "KEYNAME1", language);
    
    // TODO: implementieren wenn Attribute möglich sind
    var adma = ""
    /*var adm = getAddressData( [GetAttributeKey( "Aussendienst", "1", orgrelid, pUser )[0]],
        [["Person","function", "concat( ['SALUTATION', 'TITLE', 'FIRSTNAME','LASTNAME'])"],
        ["Telefon", "function", "getCommAddrSQL('Telefon', 'RELATION.RELATIONID')"],
        ["Email", "function", "getCommAddrSQL('E-Mail', 'RELATION.RELATIONID')"]
        ] );
    var adma = "";
    if (adm[1] != undefined)  adma = adm[1].join("\n");*/
    params["AD_Name"] = adma;
    params["SUMITEMSUM"] = sumItemSum;
    params["TOTAL"] = total;
    params["anzahl"] = countDiscounts;

    offerReport.addImage("myLogo", imgData[1]);

    offerReport.addSubReportData("subdata", ReportData.begin(["VAT","WERT"]).add(sums));
    offerReport.addReportParams(params);
    
    var data = [];
    for( i = 0; i < rptdata.length; i++)
    {
        data[i] = [rptdata[i][6], rptdata[i][7], rptdata[i][8], rptdata[i][10], rptdata[i][11], rptdata[i][13], 
        rptdata[i][14], rptdata[i][15], rptdata[i][16], rptdata[i][18], rptdata[i][19], //10
        rptdata[i][22], rptdata[i][23], 
        rptdata[i][24], rptdata[i][25], rptdata[i][26], rptdata[i][27], rptdata[i][28], rptdata[i][29]];
    }
                                                        // 0            1                    2                   3                        4
    offerReport.setReportData(ReportData.begin(["OFFER_CURRENCY", "OFFER_OFFERDATE", "OFFER_OFFERID",  "OFFERITEM_INFO", "OFFERITEM_ASSIGNEDTO",
                "OFFERITEM_ITEMNAME" , "OFFERITEM_OPTIONAL", "OFFERITEM_ITEMPOSITION", "PRODUCT_PRODUCTCODE", "OFFER_FOOTER", "OFFER_HEADER", // 10
                "OFFERITEM_QUANTITY", "OFFERITEM_PRICE", "OFFERITEM_DISCOUNT", "OFFER_VERSNR", "OFFER_OFFERCODE", "OFFERITEM_VAT", "ITEMSUM", // 17
                "OFFERITEM_UNITTEXT"]) // 18
                .add(data));
    
    offerReport.openReport();
}

/******************************************************************************/

/**
 * Provides methods for dealing with offer items.
 * Inherits methods from abstract class ItemUtils.
 * For documentation, see class ItemUtils.
 * 
 * @class
 */
function OfferItemUtils(pOfferId) {
    // extends ItemUtils
    ItemUtils.apply(this, [pOfferId, "OFFER"]);
    OfferItemUtils.prototype = Object.create(ItemUtils.prototype);
    OfferItemUtils.prototype.constructor = OfferItemUtils;
}

OfferItemUtils.prototype.getNetAndVat = function(offeritemIdsToDel) {
    return ItemUtils.prototype.getNetAndVat.apply(this, [offeritemIdsToDel]);
}

OfferItemUtils.prototype.initItemTree = function() {
    ItemUtils.prototype.initItemTree.apply(this);
}

OfferItemUtils.prototype.getItemSum = function(pQuantity, pPrice, pDiscount, pOptional) {
    return ItemUtils.prototype.getItemSum.apply(this, [pQuantity, pPrice, pDiscount, pOptional]);
}

OfferItemUtils.prototype.getItemVAT = function(pQuantity, pPrice, pDiscount, pVAT, pOptional) {
    return ItemUtils.prototype.getItemVAT.apply(this, [pQuantity, pPrice, pDiscount, pVAT, pOptional]);
}

OfferItemUtils.prototype.roundPrice = function(pPrice) {
    return ItemUtils.prototype.roundPrice.apply(this, [pPrice]);
}

OfferItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCurrency, pRelationId) {
    this.initItemTree();
    
    var cols =  ["OFFERITEMID"
                , "OFFER_ID"
                , "PRODUCT_ID"
                , "GROUPCODEID"
                , "ASSIGNEDTO"
                , "ITEMNAME"
                , "UNIT"
                , "PRICE"
                , "VAT"
                , "QUANTITY"
                , "OPTIONAL"
                , "ITEMPOSITION"
                , "ITEMSORT"
                , "DATE_NEW"
                , "USER_NEW"];

    return ItemUtils.prototype.insertPartsList.apply(this, [cols, pProductId, pAssignedTo, pCurrency, pRelationId, [["INFO", "INFO"]]]);
}

OfferItemUtils.prototype.deletePartsList = function(pItemId) {
    this.initItemTree();
    
    return ItemUtils.prototype.deletePartsList.apply(this, [pItemId]);
}

OfferItemUtils.prototype.getNextItemSort = function(pIds) {
    this.initItemTree();

    return ItemUtils.prototype.getNextItemSort.apply(this, [pIds]);
}

OfferItemUtils.prototype.getNextItemPosition = function(pAssignedTo, pTree, pIds) {
    this.initItemTree();

    return ItemUtils.prototype.getNextItemPosition.apply(this, [pAssignedTo, pTree, pIds]);
}

OfferItemUtils.prototype.reOrgItems = function() {
    this.initItemTree();
    
    ItemUtils.prototype.reOrgItems.apply(this);
}