
function koCart(kart) {
    this.Id = kart.Id || '';
    this.Owner = kart.Owner || '';
    this.Name = ko.observable(kart.Name || '');
    this.OrderNumber = kart.OrderNumber || '';
    var itemArray = [];

    if (kart.Items) {
        for (var i = 0; i < kart.Items.length; i++) {
            itemArray.push(new koCartItem(kart.Items[i]));
        }
    }
    this.Items = ko.observableArray(itemArray);

    //computed
    this.ItemCount = ko.computed(function () {
        var c = 0;
        for (var i = 0; i < this.Items().length; i++) {
            var item = this.Items()[i];
            c += item.Quantity();
        }
        return c;
    }, this);

    this.KnownTotal = ko.computed(function () {
        var c = 0;
        for (var i = 0; i < this.Items().length; i++) {
            var item = this.Items()[i];
            c += item.PriceInfo.ActualPrice * item.Quantity();
        }
        return parseFloat(FixedDecimals(c, 2)).formatMoney('$');
    }, this);

    this.ItemsByRecent = ko.computed(function () {
        return this.Items; //.sortByProperty("Added");
    }, this);

    this.isDirty = ko.computed(function () {
        var dc = this.Items().reduce(function (p, itm, idx, ary) {
            if (itm.isDirty()) p += 1;
            return p;
        }, 0);
        return dc > 0;
    }, this);

    //more view aids
    this.newItems = ko.observableArray();
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    //this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });
    //this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0), PromoCode: ko.observable(''), ContractNumber: ko.observable('') });

    this.PastedData = ko.observable('');

    this.addNewItem = function () {
        this.newItems.push({ ItemId: ko.observable(''), Quantity: ko.observable(0) });
    };
    this.acceptNewItems = function () {
        var arri = [];
        for (var i = 0; i < this.newItems().length; i++) {
            if (this.newItems()[i].Quantity() > 0) {
                arri.push(ko.toJS(this.newItems()[i]));
            }
        }

        var jsonstring = JSON.stringify(arri);
        /*
        $.ajax({
        url: ko__pathToRoot + "/ideos/kartService.svc/items/update/" + new Date().getTime(),
        timeout: 20000,
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: jsonstring
        }).done(function (data) {
        pubsub.publish(pubkey_CartData, [data]);
        });
        */
        ajaxHelper.request({
            waitingText: 'Adding items to cart...',
            id: 'noty-adding-cartitems',
            url: ko__pathToRoot + "/ideos/kartService.svc/items/update/" + new Date().getTime(),
            type: "POST",
            data: jsonstring
        }).done(function (data) {
            pubsub.publish(pubkey_CartData, [data]);
        });
    };
    this.processPastedData = function () {
        //console.log('processing pasted data...', this.PastedData());

        var arri = [];

        var lines = this.PastedData().split('\n');
        for (var i = 0; i < lines.length; i++) {
            if (lines[i].length > 0) {
                var itemColumns = lines[i].split('\t');
                if (itemColumns.length < 2) {
                    itemColumns = lines[i].split(',');
                }
                if (itemColumns.length < 2) {
                    noty({ type: "error", text: "Could not parse input [" + lines[i] + "] into at least 2 columns!" });
                    return;
                }
                arri.push({ ItemId: itemColumns[0], Quantity: itemColumns[1].trim() });
            }
        }

        var jsonstring = JSON.stringify(arri);
        
        ajaxHelper.request({
            waitingText: 'Adding items to cart...',
            id: 'noty-adding-cartitems2',
            url: ko__pathToRoot + "/ideos/kartService.svc/items/update/" + new Date().getTime(),
            type: "POST",
            data: jsonstring
        }).done(function (data) {
            pubsub.publish(pubkey_CartData, [data]);
        });
    };

};

ko.utils.extend(koCart.prototype, {
    getFromServer: function () {
        var a = $.ajax({
            url: ko__pathToRoot + "/ideos/kartService.svc/getcart/" + new Date().getTime(),
            type: "GET",
            timeout: 60000
        });
        return a;
    },
    changeName: function (newname) {
        newname = newname.replace(/:/g, '.').replace(/\//g, '').replace(/\*/g, '.');
        $.ajax({
            url: ko__pathToRoot + "/ideos/kartService.svc/name/set/" + newname + "/" + new Date().getTime(),
            type: "GET",
            timeout: 20000
        }).done(function (data) {
            pubsub.publish(pubkey_CartNameChanged, [data]);
        }).fail(function (err) {
            noty({ type: 'error', text: err.statusText });
        });
    },
    removeItem: function (itemId) {
        var kitem = {};
        kitem.ItemId = itemId;
        var arry = []; arry.push(kitem);
        var jsonstring = JSON.stringify(arry);
        
        ajaxHelper.request({
            url: ko__pathToRoot + "/ideos/kartService.svc/items/remove/" + new Date().getTime(),
            type: "POST",
            waitingText: 'Removing item...',
            id: 'noty-removing-cartitem',
            data: jsonstring
        }).done(function (data) {
            pubsub.publish(pubkey_CartData, [data]);
        });
    },
    updateItem: function (koitem) {
        var arri = [];
        arri.push(ko.toJS(koitem));
        var jsonstring = JSON.stringify(arri);

        ajaxHelper.request({
            url: ko__pathToRoot + "/ideos/kartService.svc/items/update/" + new Date().getTime(),
            type: "POST",
            waitingText: 'Updating item...',
            id: 'noty-updating-cartitem',
            data: jsonstring
        }).done(function (data) {
            pubsub.publish(pubkey_CartData, [data]);
        });
    },
    update: function () {
        var arri = [];
        for (var i = 0; i < this.Items().length; i++) {
            arri.push(ko.toJS(this.Items()[i]));
        }
        var jsonstring = JSON.stringify(arri);
        
        ajaxHelper.request({
            url: ko__pathToRoot + "/ideos/kartService.svc/items/update/" + new Date().getTime(),
            type: "POST",
            waitingText: 'Updating items...',
            id: 'noty-updating-cartitems',
            data: jsonstring
        }).done(function (data) {
            pubsub.publish(pubkey_CartData, [data]);
        });
    }
});

function koCartItem(item) {
    var i = {};
    i.ContractNumber = ko.observable(item.ContractNumber);
    i.Id = item.Id;
    i.ItemId = item.ItemId;
    i.KartId = item.KartId;
    i.PoNumber = ko.observable(item.PoNumber);
    i.PromoCode = ko.observable(item.PromoCode);
    i.Quantity = ko.observable(item.Quantity);
    i.PriceInfo = {};
    i.PriceInfo.ActualPrice = FixedDecimals(item.PriceInfo.ActualPrice, 2);
    i.PriceInfo.ListPrice = FixedDecimals(item.PriceInfo.ListPrice, 2);
    i.PriceInfo.ItemId = item.PriceInfo.ItemId;
    i.PriceInfo.Uom = item.PriceInfo.Uom;
    i.Added = item.Added;
    i.Updated = item.Updated;
    i.Mode = ko.observable("item-display");

    i.Title = item.Title || '';
    i.ImageUrl = item.ImageUrl || '';
    i.DetailsPageUrl = item.DetailsPageUrl || '';


    i.dirtyFlag = new ko.DirtyFlag([ i.ContractNumber, i.PromoCode, i.Quantity ]);

    i.edit = function () {
        this.Mode("item-edit");
    };

    i.save = function () {
        return vm.cart().updateItem(this);
        this.Mode("item-display");
    };

    i.remove = function () {
        return vm.cart().removeItem(this.ItemId);
    };

    //computed
    i.lastUpdated = ko.computed(function () {
        return moment(this.Added).calendar();
    }, i);

    i.isDirty = ko.computed(function () {
        return this.dirtyFlag().isDirty();
    }, i);

    return i;
};

function koCheckout(data, kouser) {
    if (!kouser) return;
    this.ShippingMethodId = ko.observable(data.ShippingMethod || '');
    this.PoNumber = ko.observable(data.PoNumber || '');
    this.CardCode = ko.observable(data.CardCode || '');

    this.BillToId = ko.observable(data.BillToId || '');
    this.ShipToId = ko.observable(data.ShipToId || '');
    this.CardId = ko.observable(data.CardId || '');
    this.ShippingInstructions = ko.observable(data.ShippingInstructions || '');

    // ko computed
    this.ShippingAddress = ko.computed(function () {
        var sid = this.ShipToId();
        var a = null;
        a = ko.utils.arrayFirst(vm.user().AddressesForShipping(), function (item) {
            return item.LocationId() == sid;
        });
        if (a) return a;
        a = ko.utils.arrayFirst(vm.user().DropshipAddresses(), function (item) {
            return item.LocationId() == sid;
        });
        return a;
    }, this);
    this.BillingAddress = ko.computed(function () {
        var bid = this.BillToId();
        return ko.utils.arrayFirst(vm.user().AddressesForBilling(), function (item) {
            return item.LocationId() == bid;
        });
    }, this);
    this.BillingCard = ko.computed(function () {
        var cid = this.CardId();
        if (!this.BillingAddress()) return false;
        return ko.utils.arrayFirst(this.BillingAddress().Cards(), function (item) {
            return item.Id() == cid;
        });
    }, this);
    
    
    var arr = [];
    for (var i = 0; i < data.ShippingMethods.length; i++) {
        arr.push(new koShippingMethod(data.ShippingMethods[i]));
    }
    this.ShippingMethods = ko.observableArray(arr);

    this.ShippingMethod = ko.computed(function () {
        var smid = this.ShippingMethodId();
        return ko.utils.arrayFirst(this.ShippingMethods(), function (item) {
            return item.Code() == smid;
        });
    }, this);

    /*
    var shipmet = data.ShippingMethod || '';
    if (typeof(shipmet) == 'function') shipmet = shipmet.Code();
    //console.log('shipmet', shipmet);
    if (shipmet.length > 0) {
        var match = ko.utils.arrayFirst(this.ShippingMethods(), function (item) {
            //console.log(shipmet, item.Code());
            return item.Code() == shipmet;
        });
        this.ShippingMethod(match);
    }
    */
    this.PoNumber.subscribe(function (newValue) {
        this.updatePoNumber(newValue, this.CardCode());
    }.bind(this));
    this.CardCode.subscribe(function (newValue) {
        this.updatePoNumber(this.PoNumber(), newValue);
    } .bind(this));
    this.ShippingInstructions.subscribe(function (newValue) {
        this.updateShipping({ ShippingInstructions: newValue });
    } .bind(this));

    this.ShipToId.subscribe(function (newValue) {
        vm.user().selectAddressForShipping(newValue);
    } .bind(this));
    this.BillToId.subscribe(function (newValue) {
        vm.user().selectAddressForBilling(newValue);
    } .bind(this));
    this.CardId.subscribe(function (newValue) {
        vm.user().selectCardForBilling(newValue);
    } .bind(this));
    this.ShippingMethodId.subscribe(function (newValue) {
        vm.user().selectShippingMethod(newValue);
    } .bind(this));

};
ko.utils.extend(koCheckout.prototype, {
    updatePoNumber: function (ponum, code) {
        if (ponum == "") ponum = "-";
        if (code == "") code = "-";
        
        var a = ajaxHelper.request({
            id: 'noty-updating-ponum',
            waitingText: 'Updating billing details...',
            url: ko__pathToRoot + "/ideos/kartService.svc/checkout/ponum/" + toSafeJavascriptId(ponum) + "/" + code + "/" + new Date().getTime(),
            type: "GET"
        });

        return a;
    },
    updateShipping: function (checkoutInfo) {
        var a = ajaxHelper.request({
            id: "noty-updating-shipping",
            waitingText: 'Updating shipping details...',
            url: ko__pathToRoot + "/ideos/kartService.svc/checkout/shippingdetails/" + new Date().getTime(),
            type: "POST",
            data: JSON.stringify(checkoutInfo)
        });
    }
});



function koShippingMethod(data) {
    this.Code = ko.observable(data.Code);
    this.Meaning = ko.observable(data.Meaning);
    this.Description = ko.observable(data.Description);

    /*
    this.IsSelectedForShipping = ko.computed(function () {
        if (!vm.checkout()) return false;
        if (!vm.checkout().ShippingMethod()) return false;
        return vm.checkout().ShippingMethod().Code() == this.Code();
    }, this);
    */

};