﻿/***** help function *****/

function join(s1, s2, sep)
{
    if (s1 == null || s1 == '')
        return s2;

    if (s2 == null || s2 == '')
        return s1;

    var sepLen = sep.length;

    if (s1.endsWith(sep))
        s1 = s1.subStr(0, s1.length - sepLen);

    if (s2.startsWith(sep))
        s2 = s2.subStr(sepLen);

    return s1 + sep + s2;
}

function joinPath(path1, path2)
{
    return join(path1, path2, '/');
}

function makeHash(list, hashItem)
{
    hash = new Object();
    for (var i = 0; i < list.length; i++) {
        var item = list[i];
        hash[item[hashItem]] = item;
    }
    return hash;
}

function makeValueHash(list)
{
    hash = new Object();
    for (var i = 0; i < list.length; i++) {
        var item = list[i];
        hash[item.Value] = item;
    }
    return hash;
}

function langString(id, href)
{
    var s = Language[id];
    if (href != null && href != '')
        s = '<a href="' + href + '">' + s + '</a>';
    return s;
}

/***** PackageClient *****/

var PackageClient = function(clientName, options)
{
    this.clientName = clientName;
    this.hideOnSearch = options.hideOnSearch;
    this.showOnSearch = options.showOnSearch;
    this.displayElement = $(options.displayElement);
    this.statusElement = $(options.statusElement);
    this.filtersElement = $(options.filtersElement);
    this.filterTextElement = $(options.filterTextElement);
    this.transportSelect = $(options.transportSelect);
    this.destCountrySelect = $(options.destCountrySelect);
    this.destRegionSelect = $(options.destRegionSelect);
    this.departMonthSelect = $(options.departMonthSelect);
    this.typeInputList = $(options.typeInputList);
    this.autoSearch = options.autoSearch;
    this.currencySelector = $(options.currencySelector);

    this.imagePath = 'images/';
    if (options.imagePath)
        this.imagePath = options.imagePath;

    this.logoPath = 'logos/';
    if (options.logoPath)
        this.logoPath = options.logoPath;

    this.onSearchBegin = options.onSearchBegin;
    this.onSearchDone = options.onSearchDone;

    this.init();
}

PackageClient.prototype =
{
    init: function()
    {
        this.supplierHash = new Object();
        this.destCountryHash = new Object();
        this.destRegionHash = new Object();

        this.reset();
        this.getSuppliers();
        this.initDepartMonths();

        if (!this.autoSearch)
        {
            this.initDimensions();
        }
        else
        {
            this.setSelectedType(this.autoSearch.type);
            this.getDimensions(this.createQueryEx(this.autoSearch.type, this.autoSearch.departMonth, this.autoSearch.transport, this.autoSearch.origCity, this.autoSearch.destCountry));
        }

        if (Object.isArray(this.typeInputList))
        {
            var ctx = this;
            this.typeInputList.each(function(input)
            {
                // use "click" event - "change" event does not seem to work correctly in IE
                Event.observe(input, 'click', ctx.onDimensionChanged.bindAsEventListener(ctx));
            });
        }
        Event.observe(this.departMonthSelect, 'change', this.onDimensionChanged.bindAsEventListener(this));
        Event.observe(this.transportSelect, 'change', this.onDimensionChanged.bindAsEventListener(this));
        Event.observe(this.destCountrySelect, 'change', this.onDimensionChanged.bindAsEventListener(this));
        Event.observe(this.destRegionSelect, 'change', this.onDimensionChanged.bindAsEventListener(this));
        if (this.currencySelector != null)
            this.currencySelector.hide();
    },

    reset: function()
    {
        this.packages = null;
        this.packageHash = null;
        this.pageSize = 10;
        this.pageIndex = 0;
        this.pageCount = 0;
        this.searchQuery = null;
        this.searching = false;

        this.filter = new PackageFilter();
        this.filter.client = this;
        this.showFilters();
    },

    update: function()
    {
        if (this.searchQuery)
        {
            this.showPackages();
            this.filter.update();
            this.showFilters();
        }
    },

    hideElements: function()
    {
        if (this.hideOnSearch)
        {
            this.hideOnSearch.each(function(e)
            {
                e = $(e);
                if (e)
                    e.hide();
            });
        }
    },

    showElements: function()
    {
        if (this.showOnSearch)
        {
            this.showOnSearch.each(function(e)
            {
                e = $(e);
                if (e)
                    e.show();
            });
        }
    },

    /* list methods */

    getSupplier: function(s)
    {
        if (!s)
            return null;

        if (s.SupplierId)
            s = s.SupplierId;

        return this.supplierHash[s];
    },

    /* help/utility methods */

    getMonthName: function(m)
    {
    },

    initDepartMonths: function()
    {
        var combo = this.departMonthSelect;
        combo.options.length = 0;

        var td = new Date();
        var tm = td.getMonth();
        var ty = td.getFullYear();

        this.currentMonth = tm;
        this.currentYear = ty;

        var mNames = [];

        var mn = Sys.CultureInfo.CurrentCulture.dateTimeFormat.MonthNames;
        for (var i = 0; i < 12; i++)
        {
            var y = ty;
            if (i < tm)
                y++;
            var monthName = mn[i].capitalize() + ', ' + y.toString();
            mNames[i + 1] = monthName;
        }

        this.monthNames = mNames;
    },

    fillComboMonths: function(combo, list, inclAll)
    {
        if (list)
        {
            var offset = 12 - this.currentMonth;
            var orderedList = [];

            for (var i = 1; i <= 12; i++)
            {
                var item = this.findDimensionValue(list, i.toString());
                if (!item)
                {
                    item = { Value: i, Name: '', Count: 0 };
                }
                item.Name = this.monthNames[i];
                orderedList[(i + offset - 1) % 12] = item;
            }

            this.clearCombo(combo, false);

            for (var i = 0; i < orderedList.length; i++)
            {
                var item = orderedList[i];
                var text = item.Name;
                if (item.Count > 0)
                    text += ' (' + Language['Packages_Trips'].replace('{0}', item.Count) + ')';
                else
                    text += ' (' + Language['Packages_NoTrips'] + ')';

                var opt = new Option(text, item.Value);
                opt.disabled = (item.Count == 0);
                combo.options.add(opt);
            }

            // this.fillCombo(combo, orderedList, inclAll);
        }
    },

    getRedirectUrl: function(p, orig, duration, departDate)
    {
        var q = this.searchQuery;

        var url = 'PackageRedirect.aspx?sid=' + p.SupplierId + '&pid=' + p.ProductId;

        var dd = departDate;
        if (q && !dd)
            dd = q.FromDate;
        if (dd)
            url += '&dd=' + dd.format('dd-MM-yy');

        var dur = p.Duration;
        if (duration)
            dur = duration;
        if (dur)
            url += '&dur=' + dur;

        var o = orig;
        if (q && !o)
            o = q.Origin.City;
        if (o)
            url += '&orig=' + o;

        return url;
    },

    getAvailRedirectUrl: function(p, avail, orig, duration, departDate)
    {
        if (avail.BookingUrl)
        {
            return 'PackageRedirect.aspx?sid=' + p.SupplierId + '&pid=' + p.ProductId + '&bookingUrl=' + escape(avail.BookingUrl);
        }
        else
        {
            return this.getRedirectUrl(p, orig, duration, departDate);
        }
    },

    getLogoUrl: function(p)
    {
        var id = p;
        if (p.SupplierId)
            id = p.SupplierId;
        return this.logoPath + id + '.png';
    },

    getImageUrl: function(image)
    {
        return this.imagePath + image;
    },

    getClientScript: function(script, inHref)
    {
        return (inHref ? 'javascript:' : '') + this.clientName + '.' + script;
    },

    getDestName: function(p, inclCountry)
    {
        var dest = '';
        if (p.DestName != null && p.DestName != '')
            dest = p.DestName;

        if (p.DestRegion != null && p.DestRegion != '' && p.DestRegion != dest && p.DestName != null && p.DestName != '')
            dest += ', ' + p.DestRegion;
        else if (p.DestRegion != null && p.DestRegion != '' && p.DestRegion != dest)
            dest += p.DestRegion;

        if (inclCountry && p.Destination.CountryName != null && p.Destination.CountryName != '' && p.DestName != null && p.DestName != '')
            dest += ', ' + p.Destination.CountryName;
        else if (inclCountry && p.Destination.CountryName != null && p.Destination.CountryName != '')
            dest += p.Destination.CountryName;
            
        return dest;
    },

    getPriceBasis: function(p)
    {
        if (p.PriceBasis != null && p.PriceBasis != '')
            return p.PriceBasis;
        else
            return p.Supplier.PriceBasis;
    },

    getPriceBasisText: function(p)
    {
        var priceBasis = this.getPriceBasis(p);
        if (priceBasis != null && priceBasis != '')
        {
            var text = Language['Packages_PriceBasis_' + priceBasis];
            if (text)
                return text;
        }
        return null;
    },

    formatPrice: function(price)
    {
        return '<span class="currency">' + GCurrency.current + '</span> ' + GCurrency.formatPrice(price);
    },

    formatPrice2: function(price)
    {
        return GCurrency.formatPrice(price) + ' ' + GCurrency.current;
    },

    /* query methods */

    createQuery: function()
    {
        var query = new SkyGate.Momondo.Packages.PackageQuery();
        // query.MarketCountry = 'DK';
        query.Origin = new SkyGate.Momondo.Data.Location();
        query.Destination = new SkyGate.Momondo.Data.Location();

        return query;
    },

    createQueryEx: function(type, departMonth, transport, origCity, destCountry)
    {
        var query = this.createQuery();
        query.Type = type;
        query.DepartMonth = departMonth;
        query.Transport = transport;
        query.Origin.City = origCity;
        query.Destination.Country = destCountry;
        return query;
    },

    getSelectedType: function()
    {
        var typeValue = null;
        if (Object.isArray(this.typeInputList))
        {
            this.typeInputList.each(function(item)
            {
                if (item.checked)
                    typeValue = item.value;
            });
        }
        return typeValue;
    },

    setSelectedType: function(value)
    {
        this.typeInputList.each(function(item)
        {
            if (item.value == value)
            {
                item.checked = true;
            }
        });
    },

    getSearchQuery: function()
    {
        var query = this.createQuery();

        var transport = this.transportSelect.value;
        if (transport && transport.length >= 2)
        {

            var code = transport.substr(0, 2)
            query.Transport = code;

            if (transport.length >= 5)
            {
                query.Origin.City = transport.substr(2, 3);
            }
            else
            {
                query.Origin.City = null;
            }
        }
        else
        {
            query.Transport = 0;
            query.Origin.City = null;
        }

        query.Destination.Country = this.destCountrySelect.value;
        query.DestRegion = this.destRegionSelect.value;

        this.setQueryDates(query);

        var packageType = this.getSelectedType();
        if (packageType)
            query.Type = packageType;

        return query;
    },

    setQueryDates: function(query)
    {
        var tm = this.currentMonth + 1;
        var ty = this.currentYear;

        var departMonth = parseInt(this.departMonthSelect.value, 10);
        var departYear = ty;

        if (departMonth < tm)
            departYear++;

        query.DepartMonth = departMonth;

        var fd = new Date();
        fd.setUTCFullYear(departYear, departMonth - 1, 1);
        query.FromDate = fd;

        var td = new Date();
        td.setUTCFullYear(departYear, departMonth, 1);
        query.ToDate = td;
    },

    resetQueryDates: function(query)
    {
        query.FromDate = new Date(2000, 1, 1);
        query.ToDate = new Date(2099, 1, 1);
    },

    getSuppliers: function()
    {
        PackagesWS.GetSuppliers(this.getSuppliersSuccess.bind(this), this.getPackagesFailure.bind(this));
    },

    getSuppliersSuccess: function(list)
    {
        this.supplierList = list;
        this.supplierHash = makeHash(list, 'SupplierId');

        var images = '';
        for (var i = 0; i < list.length; i++)
        {
            var s = list[i];
            if (s.AffiliateImageUrl)
                images += '<img src="' + s.AffiliateImageUrl + '" width="1" height="1" />';
        }

        this.supplierAffiliateImages = images;
    },

    clearCombo: function(combo, inclAll)
    {
        if (combo)
        {
            combo.options.length = 0;

            if (inclAll)
                combo.options.add(new Option(Language['Packages_All'], ''));

            this.setComboValue(combo, '');
        }
    },

    fillCombo: function(combo, list, inclAll)
    {
        if (combo)
        {
            this.clearCombo(combo, inclAll);

            if (list)
            {
                for (var i = 0; i < list.length; i++)
                {
                    var item = list[i];
                    // combo.options.add(new Option(dest.Name, dest.Value));
                    var text = item.Name;
                    if (text)
                    {
                        if (item.Count)
                            text += ' (' + item.Count + ')';
                        combo.options.add(new Option(text, item.Value));
                    }
                }
            }
        }
    },

    setComboValue: function(combo, value)
    {
        if (value)
            combo.value = value.toString();
        if (combo.value != value)
            combo.selectedIndex = 0;
        /*
        var sel = combo.selectedIndex;
        var idx = sel;
        var len = combo.options.length;
        while (idx >= 0 && idx < len)
        {
        var opt = combo.options[idx];
        if (!opt.disabled)
        {
        if (idx != sel)
        {
        combo.selectedIndex = idx;
        this.getDimensions();
        }
        break;
        }
        idx++;
        }
        */
    },

    /* dimension methods */

    initDimensions: function()
    {
        var query = this.createQuery();
        query.DepartMonth = this.currentMonth + 1;
        query.Transport = 1;
        query.Origin.City = 'CPH';
        query.Destination.Country = 'ES';
        this.dimensionQuery = query;

        var packageType = this.getSelectedType();
        if (packageType)
            query.Type = packageType;

        this.getDimensions(query);
    },

    getDimensions: function(query)
    {
        if (!query)
            query = this.getSearchQuery();
        this.dimensionQuery = query;
        PackagesWS.GetDimensionList(query, this.getDimensionsSuccess.bind(this), this.getPackagesFailure.bind(this));
    },

    findDimensionValue: function(list, value)
    {
        for (var i = 0; i < list.length; i++)
        {
            var dimValue = list[i];

            if (dimValue.Value == value)
            {
                return dimValue;
            }
        }
        return null;
    },

    getDimensionsSuccess: function(list)
    {
        this.dimensions = list;
        var query = this.dimensionQuery;

        this.clearCombo(this.departMonthSelect, false);
        this.clearCombo(this.transportSelect, false);
        this.clearCombo(this.destCountrySelect, true);
        this.clearCombo(this.destRegionSelect, true);

        var dimDepartMonth = this.findDimension(list, "DepartMonth");
        if (dimDepartMonth)
        {
            this.fillComboMonths(this.departMonthSelect, dimDepartMonth.Values, false);
        }

        var dimTransport = this.findDimension(list, "TransportAndOrig");
        if (dimTransport)
        {
            this.fillCombo(this.transportSelect, this.trimDimensionValues(dimTransport.Values), false);
        }

        var dimDestCountry = this.findDimension(list, "DestCountry");
        if (dimDestCountry)
        {
            this.destCountryHash = makeValueHash(dimDestCountry.Values);
            this.fillCombo(this.destCountrySelect, dimDestCountry.Values, true);
        }

        /*var dimPackType = this.findDimension(list, "Type");
        if(dimPackType)
        {
        this.setSelectedType(dimPackType);            
        }*/

        /*
        var dimDestName = this.findDimension(list, "DestName");
        if (dimDestName)
        {
        this.destNameHash = makeValueHash(dimDestName.Values);
        this.fillCombo(this.destNameSelect, dimDestName.Values, true);
        }
        */

        var dimDestRegion = this.findDimension(list, "DestRegion");
        if (dimDestRegion)
        {
            var other = this.findDimensionValue(dimDestRegion.Values, null);
            if (other)
            {
                other.Value = "NA";
                other.Name = "Other";
            }
            this.destRegionHash = makeValueHash(dimDestRegion.Values);
            this.fillCombo(this.destRegionSelect, dimDestRegion.Values, true);
        }

        this.setComboValue(this.departMonthSelect, query.DepartMonth);
        this.setComboValue(this.transportSelect, this.makeTransportAndOrig(query.Transport, query.Origin.City));
        this.setComboValue(this.destCountrySelect, query.Destination.Country);
        this.setComboValue(this.destRegionSelect, query.DestRegion);
        this.setSelectedType(query.Type);

        if (this.autoSearch)
        {
            this.search();
        }
    },

    makeTransportAndOrig: function(transport, origCity)
    {
        var code = transport.toString();
        if (code && code.length == 1)
            code = '0' + code;
        if (code && origCity)
            code += origCity;
        return code;
    },

    findDimension: function(list, name)
    {
        if (list && name)
        {
            for (var i = 0; i < list.length; i++)
            {
                var dim = list[i];
                if (dim.Name == name)
                    return dim;
            }
        }
        return null

    },

    findSubDimension: function(dim, value)
    {
        if (dim != null && value != null)
        {
            var dimValue = this.findDimensionValue(dim.Values, value);
            if (dimValue && dimValue.SubDimensions && dimValue.SubDimensions.length > 0)
            {
                return dimValue.SubDimensions[0];
            }
        }
        return null;
    },

    trimDimensionValues: function(values)
    {
        var newValues = new Array();
        values.each(function(item)
        {
            if (item.Value)
                newValues.push(item);
        });
        return newValues;
    },

    onDimensionChanged: function(ev)
    {
        this.getDimensions();
    },

    /* search methods */

    searchBegin: function()
    {
        this.searching = true;

        this.updateStatus();
        this.statusElement.show();

        if (this.onSearchBegin)
            this.onSearchBegin();
    },

    searchDone: function()
    {
        if (this.searching)
        {
            this.searching = false;
            this.autoSearch = null;

            this.updateStatus();
            if (this.onSearchDone)
                this.onSearchDone();
        }
    },

    search: function(query)
    {
        this.reset();

        this.hideElements();
        this.showElements();

        if (this.displayElement)
            this.displayElement.show();

        if (this.currencySelector)
            this.currencySelector.show();

        this.pageIndex = 0;
        if (!query)
        {
            query = this.getSearchQuery();
        }
        this.searchQuery = query;

        this.searchBegin();

        PackagesWS.GetPackages(query, this.getPackagesSuccess.bind(this), this.getPackagesFailure.bind(this));
    },

    searchEx: function(month, transport, origCity, destCountry)
    {
        this.hideElements();
        this.showElements();

        this.setComboValue(this.departMonthSelect, month);
        this.setComboValue(this.transportSelect, this.makeTransportAndOrig(transport, origCity));
        this.setComboValue(this.destCountrySelect, destCountry);

        var query = this.createQuery();
        query.DepartMonth = month;
        query.Transport = transport;
        query.Origin.City = origCity;
        query.Destination.Country = destCountry;
        this.dimensionQuery = query;

        this.getDimensions(query);
    },

    applyAutoFilters: function()
    {
        if (this.autoSearch.supplier)
            this.filter.includeOnly("Supplier", this.autoSearch.supplier);
    },

    getPackagesSuccess: function(packages)
    {
        this.setPackages(packages);
        if (this.autoSearch)
        {
            this.applyAutoFilters();
        }
        this.processPackages();
        this.searchDone();
    },

    getPackagesFailure: function(e)
    {
        this.searchDone();
        this.display(e);
    },

    completePackage: function(packageId, callback)
    {
        var query = this.searchQuery;
        PackagesWS.GetPackageEx(packageId, query, callback.bind(this), this.getPackagesFailure.bind(this));
    },

    _completePackage: function(p)
    {
        if (p)
        {
            var cur = this.packageHash[p.PackageId];
            if (cur)
            {
                this.preparePackage(p);
                p.complete = true;
                p.index = cur.index;
                p.filteredIndex = cur.filteredIndex;
                this.packages[p.index] = p;
                this.filteredPackages[p.filteredIndex] = p;
                this.packageHash[p.PackageId] = p;
            }
        }
    },

    display: function(html)
    {
        this.displayElement.update(html);
    },

    setPackages: function(packages)
    {
        if (packages == null)
            packages = new Array();

        this.packages = packages;

        var hash = new Object();
        for (var i = 0; i < packages.length; i++)
        {
            var p = packages[i];
            p.index = i;
            hash[p.PackageId] = p;
            this.preparePackage(p);
            this.filter.preparePackage(p);
        }
        this.packageHash = hash;
        this.filter.modified = true;
    },

    processPackages: function()
    {
        var filtered = this.filterPackages(this.packages);
        this.filteredPackages = filtered;
        this.pageCount = Math.ceil(filtered.length / this.pageSize);
        this.setPage(this.pageIndex); // check bounds

        this.showPackages();
        this.showFilters();
    },

    preparePackage: function(p)
    {
        p.Supplier = this.supplierHash[p.SupplierId];
        if (!p.Supplier)
        {
            p.Supplier = new Object();
            p.Supplier.Name = '';
        }

        var c = this.destCountryHash[p.Destination.Country];
        if (c)
            p.Destination.CountryName = c.Name;
    },

    filterPackages: function(packages)
    {
        var list = new Array();
        for (var i = 0; i < packages.length; i++)
        {
            var p = packages[i];
            if (this.filter.matching(p))
            {
                p.filteredIndex = list.length;
                list.push(p);
            }
        }
        return list;
    },

    showPackages: function()
    {
        var html = '';

        if (this.packages.length == 0)
            html = this.getPackagesNoResultsHtml();
        else if (this.filteredPackages.length == 0)
            html = this.getPackagesNoMatchesHtml();
        else
            html = this.getPackagesHtml(this.filteredPackages);

        this.display(html);
    },

    /* page nav methods */

    setPage: function(pageIndex)
    {
        this.pageIndex = pageIndex;
        if (this.pageIndex >= this.pageCount)
            this.pageIndex = this.pageCount - 1;
        if (this.pageIndex < 0)
            this.pageIndex = 0;
    },

    showPage: function(pageIndex)
    {
        this.setPage(pageIndex);
        this.showPackages();
    },

    showFirstPage: function()
    {
        this.setPage(0);
        this.showPage(this.pageIndex);
    },

    showLastPage: function()
    {
        this.setPage(this.pageCount - 1);
        this.showPage(this.pageIndex);
    },

    showPrevPage: function()
    {
        this.setPage(this.pageIndex - 1);
        this.showPage(this.pageIndex);
    },

    showNextPage: function()
    {
        this.setPage(this.pageIndex + 1);
        this.showPage(this.pageIndex);
    },

    /* filter methods */

    showFilters: function()
    {
        this.updateFilterText();
        if (this.filtersElement && this.filter.modified)
        {
            var html = this.getFiltersHtml();
            this.filtersElement.update(html);
            this.filter.modified = false;
        }
    },

    updateFilterText: function()
    {
        if (this.filterTextElement && this.packages)
        {
            var html = new Sys.StringBuilder();

            html.append('<div style="margin: 10px">');
            html.append(String.format(Language['Packages_FilterText'], this.packages.length, this.filteredPackages.length));
            html.append('</div>');
            html.append('<div class="linesep2"></div>');
            this.filterTextElement.update(html.toString());
        }
    },

    getFilterId: function(type, value)
    {
        return 'filter' + type + value;
    },

    filterRadioClick: function(type, value)
    {
        this.filter.setFilter(type, value);
        this.processPackages();
    },

    filterSelectClick: function(id)
    {
        this.processPackages();
    },

    filterClick: function(type, value)
    {
        var cb = $(this.getFilterId(type, value));
        if (cb.checked)
            this.filter.include(type, value);
        else
            this.filter.exclude(type, value);
        this.processPackages();
    },

    filterOnly: function(type, value)
    {
        this.filter.includeOnly(type, value);
        this.showFilters(); // update filters
        this.processPackages();
    },

    unfilter: function(type)
    {
        this.filter.includeAll(type);
        this.processPackages();
    },

    /* avail popup methods */

    getPopup: function(p)
    {
        var popup = $('popup');
        if (p)
        {
            var panel = $('package' + p.PackageId);
            var pos = panel.positionedOffset();
            popup.style.top = (pos.top + 45) + 'px';
            //console.log(event);
            //console.log(Event.pointerX());
        }
        return popup;
    },

    hidePopup: function()
    {
        $('popup').hide();
    },

    showPopup: function(packageId)
    {
        var p = this.packageHash[packageId];
        if (p)
        {
            if (p.complete)
            {
                this._showPopup(p);
            }
            else
            {
                var html = this.getPopupWaitHtml();

                var popup = this.getPopup(p);
                popup.update(html);
                popup.show();

                this.completePackage(packageId, this.getAvailSuccess);
            }
        }
    },

    _showPopup: function(p)
    {
        var html = this.getPopupHtml(p);

        var popup = this.getPopup(p);
        popup.update(html);
        popup.show();
    },

    getAvailSuccess: function(p)
    {
        if (p)
        {
            this._completePackage(p);
            this._showPopup(p);
        }
        else
        {
            this.hidePopup();
        }
    },

    /* status methods */

    updateStatus: function()
    {
        if (this.statusElement)
        {
            var html = this.getStatusHtml();
            this.statusElement.update(html);
        }
    },

    /* rendering methods */

    getStatusHtml: function()
    {
        var query = this.searchQuery;

        var currentDestCountry = (query.Destination == null ? null : this.destCountryHash[query.Destination.Country]);
        var currentDestName = this.destRegionHash[query.DestName];

        var dest = '';
        if (currentDestName)
            dest = currentDestName.Name;
        else if (currentDestCountry)
            dest = currentDestCountry.Name;

        this.currentDest = dest;

        var img = 'blueydone.gif';
        if (this.searching)
            img = 'blueywait.gif';
        img = this.getImageUrl(img);

        var text = '';
        if (this.searching)
            text = Language['Packages_StatusSearching'];
        else
            text = String.format(Language['Packages_StatusText'], this.packages.length);

        var html = new Sys.StringBuilder();

        html.append('<div class="packagestatus">');
        html.append('<table cellpadding="0" cellspacing="0" class="status">');
        html.append('<tr>');
        html.append(String.format('<td class="caption">{0}</td>', Language['Packages_StatusCaption']));
        html.append(String.format('<td class="dest">{0}</td>', dest));
        html.append(String.format('<td class="image"><img id="StatusImage" src="{0}" /></td>', img));
        html.append(String.format('<td class="text">{0}</span></td>', text));
        html.append('</tr>');
        html.append('</table>');
        html.append('</div>');

        return html.toString();
    },

    getPackagesNoResultsHtml: function()
    {
        return '<div class="packages"><div class="warning">' + Language['Packages_NoResults'] + '</div></div>';
    },

    getPackagesNoMatchesHtml: function()
    {
        return '<div class="packages"><div class="warning">' + Language['Packages_NoMatches'] + '</div></div>';
    },

    getPackagesHtml: function(list)
    {
        var html = new Sys.StringBuilder();

        html.append('<div class="linesep2"></div>');
        html.append('<div class="packages">');

        html.append('<div id="popup" class="popup" style="display:none"></div>');

        if (this.supplierAffiliateImages)
            html.append(this.supplierAffiliateImages);

        var pageNav = this.getPageNavHtml();
        html.append(pageNav);

        var startIndex = this.pageIndex * this.pageSize;
        for (var i = 0; i < this.pageSize; i++)
        {
            var index = startIndex + i;
            if (index >= list.length) break;

            var p = list[index];
            html.append(this.getPackageHtml(p));
        }

        html.append('<div class="linesep2"></div>');
        html.append(pageNav);

        html.append('</div>'); // close "packages"

        return html.toString();
    },

    getPackageHtml: function(p)
    {
        var html = new Sys.StringBuilder();
        var id = p.PackageId;
        var redirUrl = this.getRedirectUrl(p);
        var popupScript = this.getClientScript('showPopup(' + id + ')', true);

        html.append('<div id="package' + id + '" class="package2"><a name="package' + id + '"></a>');
        html.append('<div>');

        html.append('<div style="float: left;">');
        html.append('<div class="image"><a href="' + redirUrl + '" target="_blank"><img src="' + p.ImageUrl + '" width=\"200\" onerror="' + this.getClientScript('noPicture(this)') + '"/></a></div>');
        html.append('</div>');

        html.append('<div style="margin-left: 223px;">');
        //html.append('<div style="border: 1px solid red">'); /**/
        html.append('<div class="logo2"><a href="' + redirUrl + '" target="_blank"><img class="logo" src="' + this.getLogoUrl(p) + '"></a></div>');
        html.append('<div class="header"><a href="' + redirUrl + '" target="_blank">' + p.Name.truncate(35) + '</a></div>');
        html.append('<div class="dest2">' + this.getDestName(p, true) + '</div>');

        html.append('<div class="linesep2"></div>');

        /* col2 start */
        html.append('<div style="float: right; width: 102px; text-align: right">');

        //var priceLink2 = '<a class="price" href="' + popupScript + '">';

        var hasPrices2 = false;
        for (var i = 0; i < p.PriceInfo.length; i++)
        {
            hasPrices2 = true;
            var priceInfo2 = p.PriceInfo[i];
            if (this.filter.matchPriceInfo(priceInfo2))
            {
                html.append('<div class="prices_from2">(' + String.format(Language['Packages_PricesFromDays'], priceInfo2.Duration) + ')</div>');
                //html.append('<div class="price2">' + priceLink2 + this.formatPrice(priceInfo2.PriceEUR) + '</a></div>');
                html.append('<div class="price2"><a href="' + popupScript + '">' + this.formatPrice2(priceInfo2.PriceEUR) + '</a></div>');
            }
        }

        if (!hasPrices2)
        {
            html.append('<div class="prices_from2">(' + Language['Packages_PricesFrom'] + ')</div>');
            html.append('<div class="price2"><a href="' + popupScript + '">' + this.formatPrice2(p.PriceEUR) + '</a></div>');
        }


        html.append('</div>');
        /* col2 end */

        /* col1 start */
        html.append('<div style="margin-right: 112px">');
        html.append('<div style="margin: 10px 0px"><img src="' + this.getImageUrl('stjerner_' + p.HotelRating + '.png') + '" /></div>');
        html.append('<div class="body2">' + p.ShortText + '</div>');
        html.append('</div>');
        /* col1 end */

        html.append('<div style="clear: both"></div>');

        /* actions start */
        html.append('<div style="text-align: right">');
        html.append('<div class="actions2">' + langString('Packages_DatesAndPrices', popupScript) + '</div>');
        html.append('<div class="button"><input type="button" class="button" onclick="window.open(\'' + redirUrl + '\')" value="' + Language['Packages_Visit'] + '" /></a></div>');
        var priceBasis2 = this.getPriceBasisText(p);
        if (priceBasis2)
            html.append('<div class="pricetext2">' + priceBasis2 + '</div>');
        html.append('</div>');
        /* actions end */

        //html.append('</div>'); /**/
        html.append('</div>');

        html.append('</div>');
        html.append('</div>'); // close "package"

        /* */
        return html.toString();

        html.append('<table cellspacing="0" cellpadding="0" border="0"><tr>');
        html.append('<td class="image"><div class="image"><a href="' + redirUrl + '" target="_blank"><img src="' + p.ImageUrl + '" width=\"250\" onerror="' + this.getClientScript('noPicture(this)') + '"/></a></div></td>');
        html.append('<td class="text"><div class="text">');
        html.append('<div class="header"><a href="' + redirUrl + '" target="_blank">' + p.Name + '</a></div>');
        html.append('<div class="dest">' + this.getDestName(p, true) + '</div>');
        html.append('<div class="stars"><img src="' + this.getImageUrl('stars_gold' + p.HotelRating + '.gif') + '" /></div>');
        html.append('<div class="body">' + p.ShortText + '</div></div></td>');
        html.append('<td class="price"><div class="prices">');

        html.append('<div class="logo"><a href="' + redirUrl + '" target="_blank"><img class="logo" src="' + this.getLogoUrl(p) + '"></a></div>');
        html.append('<div class="actions">' + langString('Packages_DatesAndPrices', popupScript) + '</div>');

        var priceLink = '<a class="price" href="' + popupScript + '">';
        // var priceLink = '<a class="price" href="' + redirUrl + '" target="_blank">';

        var hasPrices = false;
        for (var i = 0; i < p.PriceInfo.length; i++)
        {
            hasPrices = true;
            var priceInfo = p.PriceInfo[i];
            if (this.filter.matchPriceInfo(priceInfo))
            {
                html.append('<div class="prices_from">' + String.format(Language['Packages_PricesFromDays'], priceInfo.Duration) + '</div>');
                html.append('<div class="price">' + priceLink + this.formatPrice(priceInfo.PriceEUR) + '</a></div>');
            }
        }

        if (!hasPrices)
        {
            html.append('<div class="prices_from">' + Language['Packages_PricesFrom'] + '</div>');
            html.append('<div class="price">' + priceLink + this.formatPrice(p.PriceEUR) + '</a></div>');
        }

        var priceBasis = this.getPriceBasisText(p);
        if (priceBasis)
            html.append('<div class="pricetext">' + priceBasis + '</div>');

        html.append('<div class="button"><input type="button" class="button" onclick="window.open(\'' + redirUrl + '\')" value="' + Language['Packages_Visit'] + '" /></a></div>');

        html.append('</div></td>'); // close "prices"
        html.append('</tr></table>');

        html.append('</div>'); // close "package"

        return html.toString();
    },

    noPicture: function(e)
    {
        e.src = this.getImageUrl('nopic.png');
    },

    getPageNavHtml: function()
    {
        var pg = this.pageIndex;
        var pc = this.pageCount;

        if (pc == 0)
            return '';

        var sep = '&nbsp;|&nbsp;';

        var html = new Sys.StringBuilder();

        html.append('<div class="pagenav">');
        //html.append(langString('Packages_FirstPage', (pg > 0 ? this.getClientScript('showFirstPage()', true) : null)));
        //html.append(sep);
        //html.append(langString('Packages_PrevPage', (pg > 0 ? this.getClientScript('showPrevPage()', true) : null)));
        //html.append(sep);

        if (pg > 0)
        {
            html.append(langString('Packages_FirstPage', this.getClientScript('showFirstPage()', true)));
            html.append(sep);
            html.append(langString('Packages_PrevPage', this.getClientScript('showPrevPage()', true)));
            html.append(sep);
        }

        var start = pg - 4;
        var stop = pg + 5;
        start = Math.min(start, pc - 9);
        start = Math.max(start, 0);
        stop = Math.max(stop, 9)
        stop = Math.min(stop, pc);

        if (stop != 1)
        {
            for (var i = start; i < stop; i++)
            {
                var pageNo = (i + 1);
                if (i == pg)
                    html.append('<span class="currentpage">' + pageNo.toString() + '</span>');
                else
                    html.append('<a href="' + this.getClientScript('showPage(' + i.toString() + ')', true) + '">' + pageNo.toString() + '</a>');
                html.append(sep);
            }
        }

        //html.append(langString('Packages_NextPage', (pg < pc - 1 ? this.getClientScript('showNextPage()', true) : null)));
        //html.append(sep);
        //html.append(langString('Packages_LastPage', (pg < pc - 1 ? this.getClientScript('showLastPage()', true) : null)));

        if (pg < pc - 1)
        {
            html.append(langString('Packages_NextPage', this.getClientScript('showNextPage()', true)));
            html.append(sep);
            html.append(langString('Packages_LastPage', this.getClientScript('showLastPage()', true)));
        }

        html.append('</div>');

        return html.toString();
    },

    getPopupWaitHtml: function(p)
    {
        return '<div class="wait"><div class="waittext">' + Language["Packages_Popup_WaitText"] + '</div><img src="' + this.getImageUrl('wait.gif') + '"></div>';
    },

    getPopupHtml: function(p)
    {
        var html = new Sys.StringBuilder();

        // var closeScript = '$(\'popup_' + p.PackageId + '\').hide();';
        var closeScript = this.getClientScript('hidePopup()');

        var durations = new Array();
        for (var j = 0; j < p.PriceInfo.length; j++)
        {
            var priceInfo = p.PriceInfo[j];
            durations[j] = priceInfo.Duration;
        }

        var header = '';
        var caption = '';
        for (var j = 0; j < durations.length; j++)
        {
            var text = String.format(Language['Packages_XDays'], durations[j])
            caption += '<td class="days">' + text + '</td>';

            if (j == durations.length - 1)
                header += '<img src="' + this.getImageUrl('x_blue.png') + '" onclick="' + closeScript + '" />';
            else
                header += '&nbsp;';
        }

        var dayNameFormat = Language['Packages_PopupDayNameFormat'];
        var showDayNames = (dayNameFormat != null && dayNameFormat != '');
        var colspan = '';
        if (showDayNames)
            colspan = ' colspan="2"';

        var colCount = p.PriceInfo.length + (showDayNames ? 2 : 1);
        width = p.PriceInfo.length * 100 + 120;

        if (width <= 220) width = 300;

        html.append('<div class="popupbody" style="width:' + width + 'px">');
        html.append('<div style="float: right; margin-top: 10px; margin-right: 10px; cursor: pointer">' + header + '</div>');
        html.append('<div class="header">' + Language['Packages_DatesAndPrices'] + '</div>');
        html.append('<div class="back">');
        html.append('<table cellpadding="0" cellspacing="0" class="popup">');

        //html.append('<tr class="header"><td' + colspan + '>' + Language['Packages_DatesAndPrices'] + '</td>' + header + '</tr>');
        html.append('<tr class="caption"><td' + colspan + '>' + Language['Packages_Departure'] + '</td>' + caption + '</tr>');

        var alt = false;
        var len = p.Availability.length;
        var j = 0;
        while (j < len)
        {
            var a = p.Availability[j];

            if (alt)
                html.append('<tr class="alt">');
            else
                html.append('<tr>');

            if (showDayNames)
                html.append('<td class="weekday" colspan="2">' + a.DepartDate.format(dayNameFormat) + ' ' + a.DepartDate.format(Language['Packages_PopupDateFormat']) + '</td>');
            //html.append('<td class="date">' + a.DepartDate.format(Language['Packages_PopupDateFormat']) + '</td>');

            for (var jn = 0; jn < durations.length; jn++)
            {
                var an = p.Availability[j];

                if (an != null && an.DepartDate.getTime() == a.DepartDate.getTime() && an.Duration == durations[jn])
                {
                    // var url = this.getRedirectUrl(p, null, an.Duration, an.DepartDate);
                    var url = this.getAvailRedirectUrl(p, an, null, an.Duration, an.DepartDate);
                    var link = '<a href="#package' + p.PackageId + '" onclick="window.open(\'' + url + '\');' + closeScript + ';return false;">';
                    html.append('<td class="price">' + link + this.formatPrice(an.PriceEUR) + '</a></td>');
                    j++;
                }
                else
                {
                    html.append('<td class="price">-</td>');
                }
            }
            html.append('</tr>');
            alt = !alt;
        }

        html.append('</table>');

        var redirUrl = this.getRedirectUrl(p);

        html.append('<div class="footer">');
        var priceBasis = this.getPriceBasisText(p);
        if (priceBasis)
            html.append('<div class="pricetext">' + priceBasis + '</div>');
        html.append('<div class="visit"><a href="#package' + p.PackageId + '" onclick="window.open(\'' + redirUrl + '\');' + closeScript + ';return false;">' + String.format(Language['Packages_VisitSupplier'], p.Supplier.Name) + '</a></div>');
        html.append('</div>'); // close "footer"
        html.append('<div class="clearfloats"></div>');
        html.append('</div>'); // close *back*

        html.append('</div>'); // close "popupbody"

        return html.toString();
    },

    getFilterHtml: function(type, value, text)
    {
        var id = this.getFilterId(type, value);

        var filterClickScript = this.getClientScript('filterClick(\'' + type + '\',\'' + value + '\')');
        var filterOnlyScript = this.getClientScript('filterOnly(\'' + type + '\',\'' + value + '\')');

        var included = this.filter.isIncluded(type, value);
        var checked = (included ? 'checked="checked"' : '');

        var inputType = 'checkbox';
        var input = '<input type="' + inputType + '" id="' + id + '" name="' + type + '" onclick="' + filterClickScript + '" ' + checked + '/>';

        var content = '<div onclick="' + filterOnlyScript + '" class="filteritem">' + text + '</div>';

        return '<tr><td>' + input + '</td><td>' + content + '</td></tr>';
    },

    getFilterRadioHtml: function(type, value, text)
    {
        var id = this.getFilterId(type, value);

        var filterScript = this.getClientScript('filterRadioClick(\'' + type + '\',\'' + value + '\')');

        var isSet = this.filter.isSet(type, value);
        var checked = (isSet ? 'checked="checked"' : '');

        var inputType = 'radio';
        var input = '<input type="' + inputType + '" id="' + id + '" name="' + type + '" onclick="' + filterScript + '" ' + checked + '/>';

        var content = '<div onclick="' + filterScript + '" class="filteritem">' + text + '</div>';

        return '<tr><td>' + input + '</td><td>' + content + '</td></tr>';
    },

    /*getFilterSelectHtml: function(type, values, texts, selectedValue, id, onChangeCallBack, nameOfSelect)
    {
    var filterScript = this.getClientScript('filterSelectClick(\'' + id + '\')');

        var isSet = this.filter.isSet(type, selectedValue);
    var checked = (isSet ? 'checked="checked"' : '');

        var input = '<tr><td>' + Language[nameOfSelect] + '</td><td> <select id="' + id + '" onchange="' + onChangeCallBack + filterScript + '" class="filterselect">';

        for (var i = 0; i < values.length; i++)
    {
    input += '<option value="' + values[i] + '"' + (values[i] == selectedValue ? ' selected="selected"' : '') +
    '>' + texts[i] + '</option>';
    }

        input += '</select></td></tr>';

        return input; //'<tr><td>' + +'</td></tr>';
    },*/

    getFiltersHtml: function()
    {
        if (this.packages == null || this.packages.length == 0)
            return '';

        var html = new Sys.StringBuilder();
        var list = null;

        var unfilter = '<div class="unfilter"><a href="' + this.getClientScript('unfilter(\'{0}\')', true) + '">' + Language['Packages_FilterShowAll'] + '</a></div>';

        html.append('<div class="linesep2"></div>');
        html.append('<div class="filters">');

        // Suppliers

        html.append('<div class="filter">');
        html.append('<h2>' + String.format(unfilter, 'Supplier') + Language['Packages_FilterSuppliers'] + '</h2>');
        html.append('<table cellspacing="0" cellpadding="0">');
        list = this.filter.getSortedListAll('Supplier');
        for (var i = 0; i < list.length; i++)
        {
            var s = list[i];
            var imgUrl = this.getLogoUrl(s.key);
            var text = '<img src="' + imgUrl + '" class="logo" alt="' + s.value + '" />';
            html.append(this.getFilterHtml('Supplier', s.key, text));
        }
        html.append('</table>');
        html.append('</div>'); // close ".filter"

        // Hotel Ratings
        html.append('<div class="linesep2"></div>');
        html.append('<div class="filter">');
        html.append('<h2>' + String.format(unfilter, 'HotelRating') + Language['Packages_FilterHotelRatings'] + '</h2>');
        html.append('<table cellspacing="0" cellpadding="0">');
        for (var i = 0; i <= 5; i++)
        {
            var imgUrl = this.getImageUrl('stjerner_' + i + '.png');
            var text = '<img src="' + imgUrl + '" />';

            html.append(this.getFilterHtml('HotelRating', i, text));
        }
        html.append('</table>');
        html.append('</div>'); // close ".filter"

        /*// Depart date
        html.append('<div class="filter">');
        html.append('<h2>' + String.format(unfilter, 'DepartDate') + Language['Packages_FilterDepartDate'] + '</h2>');
        html.append('<table cellspacing="0" cellpadding="0">');

        var days = new Date().getMonthDays($F('SelectDepartMonth') - 1);
        var texts = new Array();
        var values = new Array();
        var ty = new Date().getFullYear();
        var tmpDate = new Date();

        if ($F('SelectDepartMonth') - 1 < tmpDate.getMonth)
        {
        ty = new Date().getFullYear() + 1;
        }

        //if($F('SelectDepartMonth').getMonth
        var iterationDate = new Date();

        iterationDate.setMonth($F('SelectDepartMonth') - 1);

        if (iterationDate.getMonth() > new Date().getMonth())
        {
        for (var f = 1; f <= days; f++)
        {
        texts.push(new Date(ty, $F('SelectDepartMonth') - 1, f).localeFormat('dd MMMM yyyy'));
        values.push(f);
        }
        }
        else
        {
        for (var f = tmpDate.localeFormat('dd'); f <= days; f++)
        {
        texts.push(new Date(ty, $F('SelectDepartMonth') - 1, f).localeFormat('dd MMMM yyyy'));
        values.push(f);
        }
        }

        html.append(this.getFilterSelectHtml('DepartDate', values, texts, 1, 'filterDepartDateFrom', 'departDateOnchange();', 'Packages_FilterDepartDateFrom'));
        html.append(this.getFilterSelectHtml('DepartDate', values, texts, values[values.length - 1], 'filterDepartDateTo', '', 'Packages_FilterDepartDateTo'));

        html.append('</table>');
        html.append('</div>'); // close ".filter"
        */
        // Durations
        html.append('<div class="linesep2"></div>');
        html.append('<div class="filter">');
        html.append('<h2>' + String.format(unfilter, 'Duration') + Language['Packages_FilterDuration'] + '</h2>');
        html.append('<table cellspacing="0" cellpadding="0">');
        list = this.filter.getSortedListAll('Duration');
        for (var i = 0; i < list.length; i++)
        {
            var dur = list[i].value;
            var text = String.format(Language['Packages_XDays'], dur);
            html.append(this.getFilterHtml('Duration', dur, text));
        }
        html.append('</table>');
        html.append('</div>'); // close ".filter"

        // Price
        html.append('<div class="linesep2"></div>');
        html.append('<div class="filter">');
        html.append('<h2>' + Language['Packages_FilterPrice'] + '</h2>');
        html.append('<table cellspacing="0" cellpadding="0">');
        for (var i = 0; i < this.filter.priceRanges.length; i++)
        {
            var text = this.filter.priceRangesText[i];
            html.append(this.getFilterRadioHtml('Price', i, text));
        }
        html.append('</table>');
        html.append('</div>'); // close ".filter"

        if (!this.searchQuery.Destination.Country)
        {
            // DestCountry
            html.append('<div class="filter">');
            html.append('<h2>' + String.format(unfilter, 'DestCountry') + Language['Packages_FilterDestCountry'] + '</h2>');
            html.append('<table cellspacing="0" cellpadding="0">');
            list = this.filter.getSortedListAll('DestCountry');
            for (var i = 0; i < list.length; i++)
            {
                var item = list[i];
                html.append(this.getFilterHtml('DestCountry', item.key, item.value));
            }
            html.append('</table>');
            html.append('</div>'); // close ".filter"
        }

        if (!this.searchQuery.DestName)
        {
            html.append('<div class="linesep2"></div>');
            // DestRegion // Using DestName as identifier for the headline
            html.append('<div class="filter">');
            html.append('<h2>' + String.format(unfilter, 'DestRegion') + Language['Packages_FilterDestName'] + '</h2>');
            html.append('<table cellspacing="0" cellpadding="0">');
            list = this.filter.getSortedListAll('DestRegion');
            for (var i = 0; i < list.length; i++)
            {
                var item = list[i];
                var id = item.key;
                var text = item.value;
                if (id == null || id == '')
                {
                    id = '';
                    text = Language['Packages_FilterDestRegion_Other'];
                }
                html.append(this.getFilterHtml('DestRegion', id, text));
            }
            html.append('</table>');
            html.append('</div>'); // close ".filter"

            /*if (this.searchQuery.Destination.Country)
            {
            // DestName
            html.append('<div class="filter">');
            html.append('<h2>' + String.format(unfilter, 'DestName') + Language['Packages_FilterDestName'] + '</h2>');
            html.append('<table cellspacing="0" cellpadding="0">');
            list = this.filter.getSortedListAll('DestName');
            for(var i = 0; i < list.length; i++)
            { 
            var item = list[i];
            html.append(this.getFilterHtml('DestName', item.key, item.value));
            }
            html.append('</table>');
            html.append('</div>'); // close ".filter"
            }*/
        }

        html.append('<div style="padding-bottom: 10px"></div>');
        html.append('</div>'); // close "#filters"

        return html.toString();
    }
}

/***** Function test by brh *****/
/*
function departDateOnchange()
{
if ($F('filterDepartDateFrom') > $F('filterDepartDateTo'))
{
$('filterDepartDateTo').options[$('filterDepartDateFrom').selectedIndex].selected = true;
}

for (var i = 0; i < $('filterDepartDateTo').options.length; i++)
{
if ($('filterDepartDateTo').options[i].value < $F('filterDepartDateFrom'))
{
$('filterDepartDateTo').options[i].disabled = true;
}
else
{
$('filterDepartDateTo').options[i].disabled = false;
}
}
}*/

/***** PackageFilter *****/

var PackageFilter = function()
{
    this.reset();
}

PackageFilter.prototype =
{
    reset: function()
    {
        this.modified = true;
        this.excludeHotelRating = new Array();
        this.excludeSupplier = new Array();
        this.excludeDuration = new Array();
        this.excludeDestCountry = new Array();
        this.excludeDestRegion = new Array();
        this.excludeDestName = new Array();
        this.priceRange = 0;

        this.suppliers = new Dictionary();
        this.durations = new Dictionary();
        this.destCountries = new Dictionary();
        this.destRegions = new Dictionary();
        this.destNames = new Dictionary();

        this.update();
    },

    matching: function(p)
    {
        if (this.excludeHotelRating.contains(p.HotelRating.toString()))
            return false;

        if (this.excludeSupplier.contains(p.SupplierId))
            return false;

        if (this.excludeDestCountry.contains(p.Destination.Country))
            return false;

        if (this.excludeDestRegion.contains(p.DestRegion))
            return false;

        if (this.excludeDestName.contains(p.DestName))
            return false;

        if (!this.matchPriceInfos(p))
            return false;

        /*if (!this.matchDepartDates(p))
        return false;*/

        return true;
    },

    /*matchDepartDates: function(p)
    {
    var pi = p.PriceInfo;
    var len = pi.length;
    for (var i = 0; i < len; i++)
    {
    var item = pi[i];

            if (this.matchDepartDate(item))
    return true;
    }
    return false;
    },

    matchDepartDate: function(priceInfo)
    {
    var included = true;

        // check departdate on avail
    if (!this.excludeDuration.contains(priceInfo.Duration.toString()))
    {
    var depDate = priceInfo.DepartDate.localeFormat('dd');

            if ($('filterDepartDateFrom') != null && $('filterDepartDateTo') != null)
    {
    if (depDate < $F('filterDepartDateFrom') || depDate > $F('filterDepartDateTo'))
    {
    return false;
    }
    }

            return included;
    }
    },*/

    matchPriceInfos: function(p)
    {
        var pi = p.PriceInfo;
        var len = pi.length;
        for (var i = 0; i < len; i++) {
            var item = pi[i];

            if (this.matchPriceInfo(item))
                return true;
        }

        return false;
    },

    matchPriceInfo: function(priceInfo)
    {
        var included = false;

        // check duration
        if (!this.excludeDuration.contains(priceInfo.Duration.toString())) {
            included = true;

            if (this.priceRange > 0) {
                var r = this.priceRanges[this.priceRange];
                if (priceInfo.PriceEUR < r.min || priceInfo.PriceEUR >= r.max)
                    included = false;
            }
        }

        return included;
    },

    preparePackage: function(p)
    {
        this.suppliers.Add(p.SupplierId, p.Supplier.Name);

        var list = this.durations;
        var pi = p.PriceInfo;
        if (pi) {
            for (var i = 0; i < pi.length; i++) {
                var item = pi[i];
                list.Add(item.Duration.toString(), item.Duration);
            }
        }

        var c = p.Destination.CountryName;
        var r = p.DestRegion;
        this.destCountries.Add(p.Destination.Country, c);
        this.destRegions.Add(p.DestRegion, c + ', ' + r);
        if (p.DestName != r) {
            this.destNames.Add(p.DestName, (r ? r + ', ' : '') + p.DestName);
        }
    },

    update: function()
    {
        this.updatePriceRanges();
    },

    updatePriceRanges: function()
    {
        var ranges = new Array();
        var texts = new Array();

        var stepCount = 3;
        var stepEUR = 400;
        var step = GCurrency.convertFromEUR(stepEUR);
        step = Math.floor(step / 100) * 100;
        stepEUR = GCurrency.convertToEUR(step);

        var range = { 'min': 0, 'max': 0 };
        var rangeEUR = { 'min': 0, 'max': 0 };
        for (var i = 1; i < stepCount; i++) {
            range.min = range.max;
            range.max += step;

            texts[i] = range.min + ' - ' + range.max + ' ' + GCurrency.current;

            rangeEUR.min = rangeEUR.max;
            rangeEUR.max += stepEUR;

            ranges[i] = { 'min': rangeEUR.min, 'max': rangeEUR.max };
        }

        texts[stepCount] = Language['Packages_FilterPriceAbove'] + ' ' + range.max + ' ' + GCurrency.current;
        ranges[stepCount] = { 'min': rangeEUR.max, 'max': 99999999 };

        texts[0] = Language['Packages_FilterPriceAll'];
        ranges[0] = { 'min': 0, 'max': 99999999 };

        this.priceRanges = ranges;
        this.priceRangesText = texts;
    },

    setFilter: function(type, value)
    {
        switch (type) {
            case 'Price':
                this.priceRange = parseInt(value, 10);
                break;
            default:
                return;
        }
        this.modified = true;
    },

    setFilterList: function(type, list)
    {
        switch (type) {
            case 'HotelRating':
                this.excludeHotelRating = list;
                break;
            case 'Supplier':
                this.excludeSupplier = list;
                break;
            case 'Duration':
                this.excludeDuration = list;
                break;
            case 'DestCountry':
                this.excludeDestCountry = list;
                break;
            case 'DestRegion':
                this.excludeDestRegion = list;
                break;
            case 'DestName':
                this.excludeDestName = list;
                break;
            default:
                return;
        }
        this.modified = true;
    },

    getFilterList: function(type)
    {
        switch (type) {
            case 'HotelRating':
                return this.excludeHotelRating;
            case 'Supplier':
                return this.excludeSupplier;
            case 'Duration':
                return this.excludeDuration;
            case 'DestCountry':
                return this.excludeDestCountry;
            case 'DestRegion':
                return this.excludeDestRegion;
            case 'DestName':
                return this.excludeDestName;
            default:
                return new Array();
        }
    },

    getFilterListAll: function(type)
    {
        switch (type) {
            case 'HotelRating':
                return ['0', '1', '2', '3', '4', '5'];
            case 'Supplier':
                return this.suppliers;
            case 'Duration':
                return this.durations;
            case 'DestCountry':
                return this.destCountries;
            case 'DestRegion':
                return this.destRegions;
            case 'DestName':
                return this.destNames;
            default:
                return new Array();
        }
    },

    getSortedListAll: function(type)
    {
        var list = this.getFilterListAll(type);
        if (typeof (list.Pairs) == 'function') {
            var pairs = list.Pairs();
            pairs.sort(dictionaryComparePairValues);
            list = pairs;
        }
        return list;
    },

    isSet: function(type, value)
    {
        switch (type) {
            case 'Price':
                return this.priceRange.toString() == value.toString();
            default:
                return false;
        }
    },

    isIncluded: function(type, value)
    {
        var list = this.getFilterList(type);
        return !list.contains(value.toString());
    },

    exclude: function(type, value)
    {
        var list = this.getFilterList(type);
        list.push(value.toString());
        this.setFilterList(type, list);
    },

    include: function(type, value)
    {
        var list = this.getFilterList(type);
        list = list.without(value.toString());
        this.setFilterList(type, list);
    },

    includeOnly: function(type, value)
    {
        var list = this.getFilterListAll(type);
        if (typeof (list.Keys) == 'function')
            var list = list.Keys();
        list = list.without(value.toString());
        this.setFilterList(type, list);
    },

    includeAll: function(type)
    {
        this.setFilterList(type, new Array());
    }
}
