﻿///////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLE DECLARATION
///////////////////////////////////////////////////////////////////////////////
// All CityDestinations from CMS will be stored in "masterCityList"
var masterCityList;
// All CityDestinations from CMS will with non Bookable city list"
var nonBookableHotelList;
// All exclusion strings configured in AppSettings will be stored in "allExclusionStrings"
var allExclusionStrings;

///////////////////////////////////////////////////////////////////////////////
// CITY CLASS
///////////////////////////////////////////////////////////////////////////////
function City(id, searchString, name) 
{
	this.ID = id;
	this.searchString = searchString;
	this.name = name;
	this.hotels = null;
}

City.prototype.addHotel = function(hotel)
{
    if (!this.hotels)
        this.createEmptyHotels();

    this.hotels.push(hotel);
}

City.prototype.createEmptyHotels = function()
{
	this.hotels = new Array();
}

City.prototype.matches = function(stringToSearch, IsSearchStringToCompare)
{
    if(IsSearchStringToCompare)
    {
        return this.matchesSearchString(stringToSearch);
    }
    else
    {
        return this.matchesName(stringToSearch);
    }
}

City.prototype.matchesSearchString = function(searchString) 
{    
    if(startsWith(this.searchString, searchString))    
	    return true;
	else
	    return false;
}

City.prototype.matchesName = function(name)
{	
	var cityName = getDestinationAfterExclusion(this.name);
	
	if(startsWith(cityName, name))
	    return true;
	else
	    return false;
}

///////////////////////////////////////////////////////////////////////////////
// HOTEL CLASS
///////////////////////////////////////////////////////////////////////////////
function Hotel(id, searchString, name, city) 
{
	this.ID = id;
	this.searchString = searchString;
	this.name = name;
	this.cityRef = city;
}

Hotel.prototype.matches = function(stringToSearch, IsSearchStringToCompare)
{
    if(IsSearchStringToCompare)
    {
        return this.matchesSearchString(stringToSearch);
    }
    else
    {
        return this.matchesName(stringToSearch);
    }
}

Hotel.prototype.matchesSearchString = function(searchString) 
{	
	if(startsWith(this.searchString, searchString))
	    return true;
	else
	    return false;
}

Hotel.prototype.matchesName = function(name)
{	
    var hotelName = getDestinationAfterExclusion(this.name);
    
	if(startsWith(hotelName, name))
	    return true;
	else
	    return false;
}

///////////////////////////////////////////////////////////////////////////////
// EXCLUSION STRINGS
///////////////////////////////////////////////////////////////////////////////
function ExclusionStrings()
{
	this.exclusionStrings = new Array();
}

ExclusionStrings.prototype.addString = function(exclusionString)
{
	this.exclusionStrings.push(exclusionString);
}

///////////////////////////////////////////////////////////////////////////////
// UTILITY CLASSES
///////////////////////////////////////////////////////////////////////////////
function getDestinationAfterExclusion(searchString)
{
    var stringToExclude;
    
    if(allExclusionStrings != null)
    {
        if(allExclusionStrings.exclusionStrings.length > 0)
        {
            for(var exclusionCtr = 0; exclusionCtr < allExclusionStrings.exclusionStrings.length; exclusionCtr++)
            {
                stringToExclude = allExclusionStrings.exclusionStrings[exclusionCtr];
                stringToExclude = stringToExclude.toLowerCase();
                if (searchString.toLowerCase().indexOf(stringToExclude) > -1)
                {
                    searchString = trim(searchString.toLowerCase().replace(stringToExclude, ""), "");
                }
            }
        }    
    }
    
    return searchString;
}
function getMatchingDestinations(cityList, searchString, IsSearchStringToCompare)
{
    var matchingCity;
    var cityObject;
    var matchingHotel;
    var hotelObject;
    var hotelList;    
    var matchingDestinationList =  new Array();
    
    // We are removing all exclusion strings from the 
    // searchstring entered by the user.    
    searchString = getDestinationAfterExclusion(searchString);
    // Get the search string replaced with regex mapping attributes (ü|u)
    searchString = getStringAfterReplace(searchString);
    if(searchString.length > 0)
    {
        if(cityList != null)
        {
            // Iterating through the cities to verify if the 
            // searchString matches to CITY or HOTELS
            for(var cityCtr = 0; cityCtr < cityList.length; cityCtr++)
            {            
                cityObject = cityList[cityCtr];
                
                // If the searchString matches with the CityName
                if(cityObject.matches(searchString, IsSearchStringToCompare))
                {
                    matchingCity = cityObject;
                    if(cityObject.hotels !=null)
                    {                        
                        matchingDestinationList.push(matchingCity);    
                    }
                }
                else
                {
                    // If the CityName doesn't match, then verifying if any 
                    // hotels in the city matcehs to the searchString.
                    matchingCity = new City(cityObject.ID, cityObject.searchString, cityObject.name);
                    hotelList = cityObject.hotels;
                    if(hotelList != null)
                    {
                        // Iterating through the hotels to verify if the 
                        // searchString matches with HOTEL name
                        for(var hotelCtr = 0; hotelCtr < hotelList.length; hotelCtr++)
                        {
                            hotelObject = hotelList[hotelCtr];
                            if(hotelObject.matches(searchString, IsSearchStringToCompare))
                            {
                                matchingHotel = new Hotel(hotelObject.ID, hotelObject.searchString, hotelObject.name, matchingCity);
                                matchingCity.addHotel(matchingHotel);
                            }
                        }
                        
                        if(matchingCity.hotels != null)
                        {
                            if(matchingCity.hotels.length > 0)
                            {
                                matchingDestinationList.push(matchingCity);
                            }
                        }
                    }
                }
            }
        }
    }
    
    // Return the list of matching CityDestinations
    return matchingDestinationList;
}

// The mapping Array
var stringMapping = new Array();
setupStringMapping();
// Following function will setup all the mappings
// This mapping should be organised in such a way that mapping with more character strings first and others next
function setupStringMapping()
{	
	stringMapping[0]    =  "aa:(aa|å)";
	stringMapping[1]    =  "ss:(ss|ß)";
	stringMapping[2]    =  "e:(e|æ)";
	stringMapping[3]    =  "o:(o|ö|ø)";
	stringMapping[4]    =  "ö:(o|ö|ø)";
	stringMapping[5]    =  "ø:(o|ö|ø)";
	stringMapping[6]    =  "a:(a|å|æ|ä)";
	stringMapping[7]    =  "å:(a|å|æ|ä)";
	stringMapping[8]    =  "æ:(a|å|æ|ä)";
	stringMapping[9]    =  "ä:(a|å|æ|ä)";
	stringMapping[10]   =  "ü:(ü|u)";
	stringMapping[11]   =  "u:(ü|u)";
}

/*
This function will take the search string and searches character by character for the
availablility of the strings as per the stringMapping.
If it found the character it will be replaced with corresponding regex mapping and traverse to the next character
*/
function getStringAfterReplace(strToSearch)
{
	var stringToReturn = "";
	strCounter=0;
	// Traverse the string character by character
	while(strCounter<strToSearch.length)
	{
		// Total number of characters to be moved forwarded if match is found the corresponding length will be moved
		// For example if "aa" is found then strCounter will be moved by 2 characters, if none found it will be moved by only "1"
		var stringLen = 1;
		// With the current search position did we find the match and replaced
		var matchFound = false;
		
		for (i = 0; i < stringMapping.length; i++)
		{
		    key     = stringMapping[i].split(":")[0];
		    value   = stringMapping[i].split(":")[1];
		    
			keyLen = key.length;
			// Get the substring of the key length
			var currentStr = strToSearch.substring(strCounter, strCounter + keyLen);
			if (currentStr.toLowerCase() == key.toLowerCase())
			{
				// If there is a match, append the corresponding mapping string to the stringToReturn
				stringLen       = keyLen;
				stringToReturn  += value;
				matchFound      = true;
				break;
			}
		}
		
		// If the match is not found then append the current character to the stringToreturn
		if (!matchFound)
		{
			stringToReturn += strToSearch.charAt(strCounter);
		}
		// Increment the counter by the length of the key got replaced with
		strCounter += stringLen;
	}
	
	return stringToReturn;
}

function trim(str, chars) {
    return ltrim(rtrim(str, chars), chars);
}

function ltrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}

function rtrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}
