﻿/*
PropertyCart class - represents listings selected for comparison, mapping or other purposes
*/
function PropertyCart(CookieName, MaxListings, OptionalDisplayFunctionRef)
{
    // Configuration from constructor
    this.cookieName = CookieName;
    if (MaxListings && !isNaN(MaxListings) && MaxListings > 0)
        this.MaxListings = MaxListings;
    else
        this.MaxListings = 5;
    if (OptionalDisplayFunctionRef && typeof (OptionalDisplayFunctionRef) == "function")
        this.displayFunction = OptionalDisplayFunctionRef;
    else
        this.displayFunction = null;

    // Internal cookie manipulation functions
    this.getCookie = function()
    {
        if (document.cookie.length > 0) // if there are any cookies
        {
            var search = this.cookieName + "=";
            var offset = document.cookie.indexOf(search);
            if (offset != -1) // if cookie exists
            {
                offset += search.length;
                var end = document.cookie.indexOf(";", offset);
                if (end == -1)
                    end = document.cookie.length;
                return unescape(document.cookie.substring(offset, end));
            }
        }
        return ""; // cookie not found
    }
    this.setCookie = function(value) {
    	var days = 30;
    	var date = new Date();
    	date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    	document.cookie = this.cookieName + "=" + value + '; expires=' + date.toGMTString() + '; path=/';
    }
}

/*
Adds the specified listing to the cart.
Returns Boolean true/false indicator of success or failure, including showing an error message when failure occurs.
*/
PropertyCart.prototype.Add = function(ListingID, MLSListingID) {
    if (!ListingID || isNaN(ListingID) || ListingID <= 0)
        alert("Bad ListingID.");
    else if (this.Contains(ListingID))
        alert("That property has already been added.");
    else if (this.Count() >= this.MaxListings)
        alert("You have selected the maximum number of properties (" + this.Count().toString() + "). Please open the clipboard and remove some properties.");
    else {
        var cookie = this.getCookie();
        if (cookie.length > 0)
            cookie += "&" + new PropertyCartItem(ListingID, MLSListingID).ToCookieString();
        else
            cookie = new PropertyCartItem(ListingID, MLSListingID).ToCookieString();
        this.setCookie(cookie);
        this.Display();
        var ctl = document.getElementById("hPropertyTour" + ListingID);
        if (ctl != null) {
            ctl.innerHTML = "Remove from Clipboard";
        }
        return true;
    }
    return false;
}

/*
Removes all listings from the cart.
*/
PropertyCart.prototype.RemoveAll = function() {
    this.setCookie("");
    this.Display();
}

PropertyCart.prototype.Toggle = function(ListingID, MLSListingID) {
    if (!ListingID || isNaN(ListingID) || ListingID <= 0)
        alert("Bad ListingID.");
    else if (this.Contains(ListingID)) {
        this.Remove(ListingID)
    }
    else if (this.Count() >= this.MaxListings) {
    alert("You have selected the maximum number of properties (" + this.Count().toString() + "). Please open the clipboard and remove some properties.");
    }
    else {
        this.Add(ListingID, MLSListingID);
    }
    return false;
}


/*
Returns the number of listings currently in the cart.
*/
PropertyCart.prototype.Count = function()
{
    var cookie = this.getCookie();
    if (cookie.length > 0)
        return cookie.split("&").length;
    else
        return 0;
}

/*
Automatically called to display/render the current contents of the cart whenever it changes.
*/
PropertyCart.prototype.Display = function()
{
    if (this.displayFunction)
        this.displayFunction(this);
}

/*
Returns the index position of the specified listing in the cart.  If not found, returns -1.
*/
PropertyCart.prototype.IndexOf = function(ListingID)
{
    var items = this.Items();
    var search = new PropertyCartItem(ListingID);
    for (var i = 0; i < items.length; i++)
    {
        if (items[i].ListingID == search.ListingID)
            return i;
    }
    return -1;
}

/*
Returns true if the specified listing is in the cart, else false.
*/
PropertyCart.prototype.Contains = function(ListingID)
{
    return (this.IndexOf(ListingID) >= 0);
}

/*
Returns array of PropertyCartItem objects representing the current contents of the cart.
This is only a copy of the items, so manipulating them won't change what is in the cart's underlying cookie.
*/
PropertyCart.prototype.Items = function()
{
    var items = new Array();
    var cookie = this.getCookie();
    if (cookie.length > 0)
    {
        var listings = cookie.split("&");
        for (var i = 0; i < listings.length; i++)
        {
            var item = PropertyCartItem.FromCookieString(listings[i]);
            items.push(item);
        }
    }
    return items;
}

/*
Returns array of ListingIDs representing the current contents of the cart.
This is only a copy of the items, so manipulating them won't change what is in the cart's underlying cookie.
*/
PropertyCart.prototype.ListingIDs = function() {
    var items = new Array();
    var cookie = this.getCookie();
    if (cookie.length > 0) {
        var listings = cookie.split("&");
        for (var i = 0; i < listings.length; i++) {
            var item = PropertyCartItem.FromCookieString(listings[i]);
            items.push(item.ListingID);
        }
    }
    return items;
}
/*
Removes the specified listing from the cart.
Returns Boolean true/false indicator of success or failure, including showing an error message when failure occurs.

*/
PropertyCart.prototype.Remove = function(ListingID) {
	var cookie = this.getCookie();
	if (cookie.length > 0) {
		var listings = cookie.split("&");
		var search = new PropertyCartItem(ListingID);
		for (var i = 0; i < listings.length; i++) {
			var listing = PropertyCartItem.FromCookieString(listings[i]);
			if (listing.ListingID == search.ListingID) {
				var list = listings.slice(0, i);
				if (i < listings.length - 1)
					list = list.concat(listings.slice(i + 1));
				this.setCookie(list.join("&"));
				this.Display();
				var ctl = document.getElementById("hPropertyTour" + ListingID);
				if (ctl != null) {
					ctl.innerHTML = "Add to Clipboard | Map My Tour";
				}
				return true;
			}
		}
	}
	alert("That property was not selected and so it could not be removed.");
	return false;
}

/*
Moves the specified listing to the specified zero-based index position in the cart.
Returns Boolean true/false indicator of success or failure, including showing an error message when failure occurs.
*/
PropertyCart.prototype.Move = function(ListingID, NewIndex)
{
    var items = this.Items();
    if (NewIndex != null && !isNaN(NewIndex) && NewIndex >= 0 && NewIndex < items.length)
    {
        var search = new PropertyCartItem(ListingID);
        for (var i = 0; i < items.length; i++)
        {
            if (items[i].ListingID == search.ListingID)
            {
                // Shift items in array
                var temp = items[i];
                if (NewIndex > i)
                {
                    for (var j = i; j < NewIndex; j++)
                        items[j] = items[j + 1];
                }
                else
                {
                    for (var j = i; j > NewIndex; j--)
                        items[j] = items[j - 1];
                }
                items[NewIndex] = temp;

                // Delete-append list in cookie
                this.RemoveAll();
                for (var k = 0; k < items.length; k++)
                    this.Add(items[k].ListingID, items[k].MLSListingID);

                this.Display();

                return true;
            }
        }
    }
    //alert("That property could not be moved.");
    return false;
}

/*
Moves the specified listing down by one position in the cart.
Returns Boolean true/false indicator of success or failure.
*/
PropertyCart.prototype.MoveUp = function(ListingID)
{
    var i = this.IndexOf(ListingID);
    if (i >= 0)
        return this.Move(ListingID, i - 1);
    else
        return false;
}

/*
Moves the specified listing up by one position in the cart.
Returns Boolean true/false indicator of success or failure.
*/
PropertyCart.prototype.MoveDown = function(ListingID)
{
    var i = this.IndexOf(ListingID);
    if (i >= 0)
        return this.Move(ListingID, i + 1);
    else
        return false;
}


/*
PropertyCartItem class - represents a property listing in a PropertyCart
*/

function PropertyCartItem(ListingID, MLSListingID)
{
    this.ListingID = isNaN(ListingID) ? null : parseInt(ListingID.toString(), 0);
    this.MLSListingID = (MLSListingID != null) ? MLSListingID.toString() : null;
}

/*
Returns the item in the format required for storing it in the cookie for its PropertyCart.
*/
PropertyCartItem.prototype.ToCookieString = function()
{
    return escape(this.ListingID.toString()) + "=" + escape(this.MLSListingID.toString());
}

/*
Returns a PropertyCartItem, given the string that was stored for that item in a PropertyCart cookie.
*/
PropertyCartItem.FromCookieString = function(cookieString)
{
    var values = cookieString.split("=");
    if (values.length >= 2)
        return new PropertyCartItem(unescape(values[0]), unescape(values[1]));
    else if (values.length == 1)
        return new PropertyCartItem(unescape(values[0]), "unknown");
    else
        return null;
}
