/**
 * @fileoverview Compare Tool Redesign (model).
 * @name Model
 * Requires Prototype version 1.6.0 or greater.
 */

/**
 * Compare Tool Redesign Model class.
 * @author Ed Jenkins
 */
var Model = Class.create();

/**
 * Compare Tool Redesign Model prototype.
 * @scope Model.prototype
 */
Model.prototype =
{

    /**
     * ZIP code.
     */
    zip: "",

    /**
     * Inline ad.
     */
    ad: null,

    /**
     * Sponsored vehicles (an array of Car objects).
     */
    sponsoredVehicles: [],

    /**
     * The Active Tab.
     */
    tab: 1,

    /**
     * OEM flag.
     */
    oem: false,

    /**
     * The general details for OEM version.
     */
    oemDetails: null,

    /**
     * Cookie & IE6 hidden input field prefix string
     */
    cookieNamePrefix: "mi_compare_",

    /**
     * Constructor.
     * @constructor
     * @throws exception if Prototype 1.6.0 or greater is not loaded.
     */
    initialize: function()
    {
        // Make sure Prototype is included.
        var exception = "Prototype version 1.6.0 or greater is required.";
        if (typeof Prototype == "undefined")
        {
            throw(exception);
        }
        // Make sure it is version 1.6.0 or greater.
        var ver = Prototype.Version.split(".");
        var major = ver[0];
        var minor = ver[1];
        if (major < 1 || minor < 6)
        {
            throw(exception);
        }
        // Initialize cars array. - fixed-size Array object.  [0] is ignored.
        this.cars = new Array(5);
        // Make sponsoredVehicles a fixed-size Array object.  [0] is ignored.
        this.sponsoredVehicles = new Array(5);
        this.oemDetails = new Hash();

    },

    /**
     * Gets the ZIP code.
     */
    getZIP: function()
    {
        return this.zip;
    },

    /**
     * Sets the ZIP code.
     */
    setZIP: function(zip)
    {
        this.zip = zip;
    },

    /**
     * Gets a car.
     * @param {number} column which car to get.  Must be between 1 and 4.
     * @return {object} a Car object or null if there is no car in the specified column.
     */
    getCar: function(column)
    {
        // Verify parameters.
        if (column == null)
        {
            return null;
        }
        if (typeof column != "number")
        {
            return null;
        }
        if (column < 1 || column > 4)
        {
            return null;
        }
        // Get a car;
        var carsArrayFragment = null;
        try
        {
            carsArrayFragment = this.cars.slice(column, column + 1);
        }
        catch(ex)
        {
        }
        var car = null;
        if (carsArrayFragment != null)
        {
            car = carsArrayFragment[0];
        }
        // Return result.
        return car;
    },

    /**
     * Sets a car.
     * @param {number} column which car to set.  Must be between 1 and 4.
     * @param {object} car a Car object.
     */
    setCar: function(column, car)
    {
        // Verify parameters.
        if (column == null)
        {
            return;
        }
        if (typeof column != "number")
        {
            return;
        }
        if (column < 1)
        {
            return;
        }
        if (column > 4)
        {
            return;
        }
        if (car == null)
        {
            return;
        }
        // Set the car.
        var currentCar = eval(car);
        car.ctr.column = column;
        this.cars[column] = currentCar;
//console.log("model.setCar - column=%i, car=%o",column,currentCar);
//        ATC.cs.research.ctr.view.updateComparingCounts();
        //write to cookie
        this.setCarsCookie();
    },

    /**
     * Removes a car.
     * @param {number} column which car to remove.  Must be between 1 and 4.
     */
    removeCar: function(column)
    {
        // Verify parameters.
        if (column == null)
        {
            return;
        }
        if (typeof column != "number")
        {
            return;
        }
        if (column < 1 || column > 4)
        {
            return;
        }
//console.debug("model.removeCar - column=" + column);
        // Remove the car.
        this.cars[column] = null;
//        ATC.cs.research.ctr.view.updateComparingCounts();
        this.setCarsCookie();
    },

    /**
     * Gets the number of cars currently being displayed.
     * @return {number} the number of cars currently being displayed.
     */
    getCarCount: function()
    {
        // Start with column 1.
        var x = 1;
        var y = this.cars.length;
        var z = 0;
        // Loop through the cars.
        for(x=1; x<y; x++)
        {
            // If an element is not null, then there is a car there.
            if(this.cars[x] != null)
            {
                // So increment the count.
                z++;
            }
//console.debug("model.getCarCount - x=" + x + ", z=" + z + ", car=" + this.cars[x]);
        }
        // Return result.
        return z;
    },

    /**
     * Finds the first empty column.
     * @return a number between 0 and 4.
     * 0 = do nothing.
     * 1 = display the Add dialog in column 1.
     * 2 = display the Add button in column 2.
     * 3 = display the Add button in column 3.
     * 4 = display the Add button in column 4.
     */
    getFirstEmptyColumn: function()
    {
        var x = 1;
        var y = this.cars.length;
        var z = 0;
        // Loop through the cars.
        for(x=1; x<y; x++)
        {
            // If there is no car, mark the spot and stop.
            if(this.cars[x] == null)
            {
                z = x;
                break;
            }
        }
        // Return result.
        return z;
    },

    /**
     * Gets the number of nonsponsored cars currently being displayed.
     * @return {number} the number of nonsponsored cars currently being displayed.
     */
    getNonSponsoredCarCount: function()
    {
        // Start with column 1.
        var x = 1;
        var y = this.cars.length;
        var z = 0;
        // Loop through the list of cars being displayed.
        while (x < y)
        {
            // If an element is not null, then there is a car there.
            if (this.cars[x] != null)
            {
                // So increment the count.
                if (this.cars[x].ctr.adType == 0) {
                    z++;
                }
            }
            x++;
        }
        // Return result.
        return z;
    },

    /**
     * Prints the cars on the console.
     */
    debugCars: function()
    {
        var x = 0;
        var y = this.cars.length;
        for(x=0; x<y; x++)
        {
            var s = "model.debugCars - ";
            s += "id=" + x + ", ";
            var car = this.cars[x];
            if(car == null)
            {
                s += "car is null";
            }
            else
            {
                s += "year=" + car.ctr.year + ", ";
                s += "make=" + car.ctr.make + ", ";
                s += "model=" + car.ctr.model + ", ";
                s += "adType=" + car.ctr.adType + ", ";
                s += "rollup=" + car.rollup;
            }
            console.debug(s);
        }
    },

    /**
     * Gets the Vehicle ID from a column in name:value pair format
     * @return {string} the name:value pair
     */
    getVN: function(column, what)
    {
        var car = ATC.cs.research.ctr.model.getCar(column);
        var carVN = "vn" + column + ":";
        if (arguments.length > 3) {
            carVN = arguments[3] + arguments[2] + ":";
        } else if (arguments.length > 2) {
            carVN = "svn" + arguments[2] + ":";
        }
        if ((typeof car != "undefined") && (car != null)) {
            if (what == undefined) {
                what = -1;
            }
            if (what == -1) {
                what = car.ctr.adType;
            }
            if (what == car.ctr.adType) {
                carVN += car.ctr.styleId;
            }
        }
        return carVN;
    },

    /**
     * Gets the Vehicle Year from a column in name:value pair format
     * @return {string} the name:value pair
     */
    getVY: function(column, what)
    {
        var car = ATC.cs.research.ctr.model.getCar(column);
        var carVY = "vy" + column + ":";
        if (arguments.length > 3) {
            carVY = arguments[3] + arguments[2] + ":";
        } else if (arguments.length > 2) {
            carVY = "svy" + arguments[2] + ":";
        }
        if ((typeof car != "undefined") && (car != null)) {
            if (what == undefined) {
                what = -1;
            }
            if (what == -1) {
                what = car.ctr.adType;
            }
            if (what == car.ctr.adType) {
                carVY += car.ctr.year;
            }
        }
        return carVY;
    },
    /**
     * Gets the inline ad.
     * @return {object} the inline ad.
     */
    getAd: function()
    {
        return this.ad;
    },

    /**
     * Sets the inline ad.
     * @param {object} car the inline ad.
     */
    setAd: function(car)
    {
        // Verify parameters.
        if (car == null)
        {
            return;
        }
        if (typeof car != "object")
        {
            return;
        }
        // Set the ad;
        this.ad = car;
    },

    /**
     * Tests if the car is an inline ad.
     * @param {object} car the possible inline ad.
     */
    isAdbyColumn: function(column)
    {
        var car = this.getCar(column);
        //0 = normal car, 1 = inline Ad, 2 = OEM car
        if ((typeof car != "undefined") && (car != null) && (car.ctr.adType != null) && (car.ctr.adType == 1))
        {
            return true;//an inline ad
        }
        else
        {
            return false;
        }
    },

    /**
     * Tests if the car is an inline ad.
     * @param {object} car the possible inline ad.
     */
    isAdbyCar: function(car)
    {
        //0 = normal car, 1 = inline Ad, 2 = OEM car
        if ((typeof car != "undefined") && (car != null) && (car.ctr.adType != null) && (car.ctr.adType == 1))
        {
            return true;//an inline ad
        }
        else
        {
            return false;
        }
    },

    /**
     * Tests if the car is an OEM ad.
     * @param {object} car the possible inline ad.
     */
    isOEMAdbyColumn: function(column)
    {
        var car = this.getCar(column);
        //0 = normal car, 1 = inline Ad, 2 = OEM car
        if ((typeof car != "undefined") && (car != null) && (car.ctr.adType != null) && (car.ctr.adType == 2))
        {
            return true;//an inline ad
        }
        else
        {
            return false;
        }
    },

    /**
     * Gets a sponsored vehicle.
     * @param {number} column which car to get.  Must be between 1 and 4.
     * @return {object} a Car object or null if there is no car in the specified column.
     */
    getSponsoredVehicle: function(column)
    {
        // Verify parameters.
        if (column == null)
        {
            return null;
        }
        if (typeof column != "number")
        {
            return null;
        }
        if (column < 1)
        {
            return null;
        }
        if (column > 4)
        {
            return null;
        }
        // Get a car.
        var a = null;
        try
        {
            a = this.sponsoredVehicles.slice(column, column + 1);
        }
        catch(ex)
        {
        }
        var car = null;
        if (a != null)
        {
            car = a[0];
        }
        // Return result.
        return car;
    },

    /**
     * Sets a sponsored vehicle.
     * @param {number} column which car to set.  Must be between 1 and 4.
     * @param {object} car a Car object.
     */
    setSponsoredVehicle: function(column, car)
    {
        // Verify parameters.
        if (column == null)
        {
            return;
        }
        if (typeof column != "number")
        {
            return;
        }
        if (column < 1)
        {
            return;
        }
        if (column > 4)
        {
            return;
        }
        if (car == null)
        {
            return;
        }
        // Set the car.
        var c = eval(car);
        this.sponsoredVehicles[column] = c;
    },

    /**
     * Returns boolean that the Year Make Model was a sponsored vehicle so we know the car that was gotten from car_cache has sponsored data in it
     */
    isSponsoredVehiclebyYMM: function(year, make, model)
    {
        // Verify parameters.
        if (year == null)
        {
            return;
        }
        if (make == null)
        {
            return;
        }
        if (model == null)
        {
            return;
        }
        if (typeof make != "string")
        {
            return;
        }
        if (typeof model != "string")
        {
            return;
        }
        // See if we have it in the sponsoredVehicles cache.
        var r = null;
        var x = 0;
        var y = this.sponsoredVehicles.length;
        for (x = 0; x < y; x++)
        {
            var car = this.sponsoredVehicles[x];
            if (car != null)
            {
                if (car.ctr.year == year)
                {
                    if (car.ctr.make == make)
                    {
                        if (car.ctr.model = model)
                        {
                            // Found it.  Let's stop looking.
                            r = car;
                            break;
                        }
                    }
                }
            }
        }
        //it's not in the sponsoredVehicles cache.
        if (r == null)
        {
            return false;
        }

        //it is in the sponsoredVehicles cache
        return true;
    },

    /**
     * returns boolean OEM Flag.
     */
    isOEM: function()
    {
        return this.oem;
    },

    /**
     * Sets OEM general details.
     * @param {object} arrOEMCars an array of the OEM details and cars.
     */
    setOEMdetails: function(arrOEMCars)
    {
        if (arrOEMCars == null) return;

        this.oem = true;
        //oemDetails needs a list of bodyStyles too
        var listBodyStyles = "";
        arrOEMCars.cars.each(function(car, i)
        {
            if (car != null) {
                listBodyStyles += (i == 0 ? "" : ",") + car.ctr.vehicleType;
            }
        });

        this.oemDetails.set('bodyStyles', listBodyStyles);
        this.oemDetails.set('backgroundColor', arrOEMCars.backgroundColor);
        this.oemDetails.set('brandingBannerUrl', arrOEMCars.brandingBannerUrl);
        this.oemDetails.set('oemLogoUrl', arrOEMCars.oemLogoUrl);
        //this.oemDetails.set('brandingClickThroughUrl',  arrOEMCars.brandingClickThroughUrl);
        //add new URLs for separate OEM tracking of each OEM image
        this.oemDetails.set('headerTrackingUrl', arrOEMCars.headerTrackingUrl);
        this.oemDetails.set('logoTrackingUrl', arrOEMCars.logoTrackingUrl);
        this.oemDetails.set('brandingStripeTrackingUrl', arrOEMCars.brandingStripeTrackingUrl);

        //LOGO_TRACKING_URL, BRANDING_STRIPE_TRACKING_URL, & HEADER_TRACKING_URL
        this.oemDetails.set('brandingMessage', arrOEMCars.brandingMessage);
        this.oemDetails.set('compareSetId', arrOEMCars.compareSetId);
        this.oemDetails.set('linkText', arrOEMCars.linkText);
        this.oemDetails.set('name', arrOEMCars.name);
        this.oemDetails.set('oemId', arrOEMCars.oemId);
        this.oemDetails.set('showMicrositeLink', arrOEMCars.showMicrositeLink);
        this.oemDetails.set('showSpecialsPageLink', arrOEMCars.showSpecialsPageLink);
        this.oemDetails.set('ocid', arrOEMCars.ocid);
        this.oemDetails.set('oemName', arrOEMCars.oemName);

        var ctr_compare_oemDetails = arrOEMCars.compareSetId + "|" + arrOEMCars.backgroundColor + "|" + arrOEMCars.headerTrackingUrl + "|" + arrOEMCars.logoTrackingUrl + "|" + arrOEMCars.brandingStripeTrackingUrl;
        //write to OEM cookie
        this.setOEMdetailsCookie(ctr_compare_oemDetails);
    },

    /**
     * Gets OEM general details.
     */
    getOEMdetails: function()
    {
        return this.oemDetails;//.toJSON();
    },

    /**
     * Sets OEM general details Cookie.
     */
    setOEMdetailsCookie: function(ctr_compare_oemDetails)
    {
        //ocid|backgroundColor| headerTrackingUrl | logoTrackingUrl | brandingStripeTrackingUrl
        setCookie("ctr_compare_oemDetails", ctr_compare_oemDetails, null, null, null, null);
    },

    /**
     * Gets the OEM details in session from session cookies
     * Used when user arrives at page by hitting back button
     */
    getOEMdetailsFromCookie: function()
    {
        var OEMdetailsFromCookie = getCookie("ctr_compare_oemDetails");

        return OEMdetailsFromCookie;
    },

    /**
     * Gets the OEM details in session from session cookies
     * Used when user arrives at page by hitting back button
     */
    getOEMocidFromCookie: function()
    {
        var cookieDataDelimeter = "|";
        var OEMdetailsFromCookie = this.getOEMdetailsFromCookie();
        var ocidFromCookie = null;

        if (OEMdetailsFromCookie != null && OEMdetailsFromCookie != "null")
        {
            var OEMdetailsArray = OEMdetailsFromCookie.split(cookieDataDelimeter);
            //ocid|backgroundColor| headerTrackingUrl | logoTrackingUrl | brandingStripeTrackingUrl
            ocidFromCookie = OEMdetailsArray[0];
        }
        return ocidFromCookie;
    },

    /*
     * Stores currently selected compare cars to cookie to be read on back button and in Compare Buffer
     * @param {object} compareList the list of car objects currently compared
     */
    setCarsCookie: function() {
        for (var i = 0; i < 4; i++)
        {
            var car = this.cars[i + 1];
            var values;
            if ((typeof car != "undefined") && (car != null) && (!this.isAdbyCar(car) ))
            {
                values = null + "|";// cookie will have this for MI: car['tileId']
                values += car.ctr.styleId + "|";
                values += car.ctr.year + "|";
                values += car.ctr.make + "|";
                values += car.ctr.model + "|";
                values += car.ctr.firstPicture;
                /*console.log("Car Cookie %i Updated with styleId: %s",i,car.ctr.styleId);*/
            }
            else
            {
                values = '';
            }
            setCookie(this.cookieNamePrefix + i, values, null, null, null, null);
        }

    },

    /**
     * Gets the car style id's added in session from session cookies
     * Used when user arrives at page by hitting back button
     */
    getStyleIdsFromCookie: function()
    {
        var cookieDataDelimeter = "|";

        var carsDataFromCookie =
                [
                    getCookie(this.cookieNamePrefix + "0"), // mi_compare_0 is the car for column 1
                    getCookie(this.cookieNamePrefix + "1"),
                    getCookie(this.cookieNamePrefix + "2"),
                    getCookie(this.cookieNamePrefix + "3")
                ];

        var styleIds = [];

        carsDataFromCookie.each(function(carData, i)
        {
            var carDataValue = null;

            if (carData != null)
            {
                var carDataArray = carData.split(cookieDataDelimeter);
                carDataValue = carDataArray[1];
            }

            // We always need to write something to this array to maintain column sequence
            styleIds[i] = carDataValue;
        });

        return styleIds;
    },

    /**
     * Sets the active tab
     */
    setActiveTab: function(tab)
    {
        this.tab = tab;
    },

    /**
     * Gets the active tab
     */
    getActiveTab: function()
    {
        return this.tab;
    },

    /**
     * IE6 cache hack.  Gets the value from the hidden input, since IE6 is caching cookies and JSON in the inline script.
     * @param carNumber - the car you'd like to retreive (zero relative).
     */
    getValueFromHiddenInputForCar: function(carNumber)
    {
        return $F(this.cookieNamePrefix+carNumber);
    },

    /**
     * Gets an array of styleIds for all cars currently displayed.
     * If we are in OEM view, then the list will only contain sponsored cars.
     * Puts the car in the specified column first.
     * @param {number} column the first car to compare the others against.
     * @return an array of styleIds.
     */
    getStyleIdsForKeyDifferences: function(column)
    {
        // Create temp variables.
        var a = new Array();
        var car = null;
        var x = 1;
        var y = 5;
        var z = 0;
        var i = 0;
        // Start with the car in the specified column.
        car = this.getCar(column);
        if (car == null)
        {
            return a;
        }
        if (car.ctr.year < 1997)
        {
            return a;
        }
        if (this.oem == true)
        {
            if (car.ctr.adType != 2)
            {
                return a;
            }
        }
        i = car.ctr.styleId;
        a[z++] = i;
        // Loop through all of the cars.
        for (x = 1; x < y; x++)
        {
            // Get a car.
            car = this.getCar(x);
            // Skip empty columns.
            if (car == null)
            {
                continue;
            }
            // Skip if we already have it.
            if (car.ctr.styleId == i)
            {
                continue;
            }
            // Skip if older than 1997 because there is no comparison data for cars made before then.
            if (car.ctr.year < 1997)
            {
                continue;
            }
            // Add its styleId to the array.
            a[z++] = car.ctr.styleId;
        }
        // Remove duplicates.
        var r = a.uniq();
        // Return result.
        return r;
    },

    /**
     * IE6 cache hack. Saves value to hidden form field since IE6 is caching JSON inline script & old cookies.
     * @param carNumber - car that needs to be updated (zero relative).
     * @param values - the values string supplied by setCarsCookie
     */
    setHiddenInputForCar: function(carNumber,values)
    {
        $(this.cookieNamePrefix+carNumber).value= values;
    }

}

// Create an instance.
ATC.cs.research.ctr.model = new Model();
