﻿
//Create the outfitstate global variable
var outfitState;
var currentChoiceValues;
var spResponses;
var myEntries;
var myComponents;
var mySections;
var mySelectedEntries;
var inSelectedEntryEditMode = false;
var myListMode;


//HTML Container Constants
CONTAINER_SECTION = 'tabLayer';
CONTAINER_COMPONENT_SCROLLER = 'componentIcons';
CONTAINER_ITEMS = 'itemContainer';
CONTAINER_SELECTED_ENTRY_BASE = 'selectedEntrySection-';
CONTAINER_BUYBOX_DETAILS = 'buyBoxItemDetails';
CONTAINER_TOTALS = 'totals';
CONTAINER_SELECTED_ENTRIES_LIST = 'summaryDetails';


PRIMARY_SECTION_ID = 'primarySection';
PRIMARY_COMPONENT_ID = 'primaryComponent';
FINAL_REVIEW_SECTION_ID = 'LIST';
NONE_ENTRY_ID = 'NONE';

SECTION_PREFIX_ID = 'sectionTab-'

CSS_ACTIVE_TAB = 'activeTab';
CSS_INACTIVE_TAB = 'inactiveTab';

HIGHLIGHTCOLOR = '#ffff99';
NORMALCOLOR = '#ffffff';

HIGHLIGHT_START_COLOR = '#ffff99';
HIGHLIGHT_END_COLOR = '#ffffff';

ENTRY_HIGHLIGHT_COLOR = '#E6E6CC';
ENTRY_NORMAL = '#ffffff';

OUTFIT_MODE_NORMAL = 'normal';
OUTFIT_MODE_REVIEW = 'review';



function initImagePath()
{
IMAGE_MAIN_THROBBER = imagePath + 'ajax-loader1.gif';
IMAGE_PATH = imagePath;
}

//Handles the initilization of the client code load
//Load the sections and the selected entries list
function init()
{   
    initImagePath();
    //Create an instance of the outfit state object and populate
    outfitState = new Orvis.Outfitter.OutfitState();
    outfitState.CurrentOutfitID = currentOutfitID;
    outfitState.CurrentDefaultID = currentDefaultID;
    outfitState.CurrentEntryRecommendationID = currentEntryRecommendationID;
    outfitState.CurrentComponentRecommendationID = currentComponentRecommendationID;
    outfitState.ShopperID = shopperID;
    outfitState.CurrentSectionID = "";
    outfitState.CurrentComponentID = "";
    outfitState.CurrentEntryID = "";
    outfitState.OutfitMode = OUTFIT_MODE_NORMAL;
    outfitState.LastEntryIDModifiedInReview = '';
    outfitState.ImagePath = imagePath;
    
    //Add a dump method for the outfit state
    outfitState.Dump = function(){
        var dumpString = 'OutfitState\n';
        
        //Iterate through each property
        for(var i in this){
            //Except the functions...
            if(typeof this[i] != 'function'){
                dumpString += i + '==>' + this[i] + '\n';
            }
        }
        
        return dumpString;
    };
    //Create an instance of the currentchoicevalue
    currentChoiceValues = new Orvis.Outfitter.CurrentChoiceValues();
    
     //Add a function to clear all of the choice values to the CurrentChoiceValue object
    Orvis.Outfitter.CurrentChoiceValues.prototype.ClearAllChoices = function(){
        this.ChoiceValue1 = "";
        this.ChoiceValue2 = "";
        this.ChoiceValue3 = "";
        this.ChoiceValue4 = "";
    };

    //Add a function to the CurrentChoiceValue object that sets all of the properties based
    //on what is currently set in the UI
    Orvis.Outfitter.CurrentChoiceValues.prototype.SetAllChoiceValues = function(){
        if($('selChoice1'))
        {
           var choice1 = $('selChoice1');
           this.ChoiceValue1 = choice1.options[choice1.selectedIndex].value
        }
        
        if($('selChoice2'))
        {
           var choice2 = $('selChoice2');
           this.ChoiceValue2 = choice2.options[choice2.selectedIndex].value
        }
        
        if($('selChoice3'))
        {
           var choice3 = $('selChoice3');
           this.ChoiceValue3 = choice3.options[choice3.selectedIndex].value
        }
        
        if($('selChoice4'))
        {
           var choice4 = $('selChoice4');
           this.ChoiceValue4 = choice4.options[choice4.selectedIndex].value
        }
    }
    
    //Create a variable to hold the special handling responses
    spResponses = new Array();

    //Get the starting sections and display
    GetSections(true);  //selectedEntries will be loaded and built if the parameter here is set to true
    BuildSelectedEntriesTotal();
    
    
}

//Get the sections for the given outfit and build the HTML
//chainLoadSelectedEntries parameter determines if the code should then load
//the selectedEntries, the building of which sometimes uses the sections
//so they must be available
//Caused the bug in the October 2007 release.
//SDP
function GetSections(chainLoadSelectedEntries)
{
    
        Orvis.Outfitter.OutfitterService.GetSections(outfitState, function (value){
           try{ 
                mySections = new Sections(value);
                
                mySections.BuildHTML();
                
                if(chainLoadSelectedEntries){
                    LoadSelectedEntries();
                }
            
            }catch(e){
                HandlePageException(e);
            }
        }, FailedCallback);
    
    
    //Deciding not to show the wait indicator as it only happens when the page loads
    //ShowWaitIndicator(CONTAINER_SECTION);   
}


//Handles the event of a section and componet being selected. This is invoke when an entry link is clicked on the Final Review Page
function SectionAndComponentSelected(sectionID)
{
    if(!mySections.clickLock){
        mySections.clickLock = true;
        mySections.loadComponent = true;
        mySections.componentIDToSelect = outfitState.CurrentComponentID;
        mySections.Select(sectionID);
    }
}

//Handles the event of a section being selected.  Get the Components
//for this given section as HTML and set the innerHTML value
function SectionSelected(sectionID)
{
    if(!mySections.clickLock){
        mySections.clickLock = true;
        mySections.Select(sectionID);
    }
}


//Handles the event of the component being selected.  Get the entries
//for this given component as HTML and set the innerHTML value
function ComponentSelected(componentID)
{
    if(!myComponents.clickLock){
        myComponents.clickLock = true; 
        myComponents.Select(componentID);
     }
}

//Handles the selecting of components, and subsequently sections,
//When the user clicks the "previous" and "next" links
function SelectPrevNextComponent(direction){
    if(direction == 'previous'){
        myComponents.SelectPrevious(outfitState.CurrentComponentID);
    }else{
        myComponents.SelectNext(outfitState.CurrentComponentID);
    } 
}


//Loads the selected entries list for the first time
function LoadSelectedEntries(){
     Orvis.Outfitter.OutfitterService.GetSelectedEntries(outfitState, function(value){
        try{
            mySelectedEntries = new SelectedEntries(value);
            
            mySelectedEntries.BuildHTML();
        }catch(e){
                HandlePageException(e);
        }
     }, FailedCallback);
     
     ShowWaitIndicator(CONTAINER_SELECTED_ENTRIES_LIST);
}


function BuildSelectedEntriesTotal()
{
    Orvis.Outfitter.OutfitterService.GetOutfitPrice(outfitState, function(value){
        try{
            $(CONTAINER_TOTALS).innerHTML = "Total = " + value;
        }catch(e){
                HandlePageException(e);
        }
    }, FailedCallback);
    
    new Effect.Highlight(CONTAINER_TOTALS, {startcolor:HIGHLIGHT_START_COLOR, endcolor:HIGHLIGHT_END_COLOR});
}

function DisplayErrorConsole(){
    $find(errorConsoleID).show(); 
}

//Hides the Error console and resets the outfit back to the 
//first page
function onErrorConsoleOK(){
    $find(errorConsoleID).hide();  
    location.reload();  //reset the outfitter back to the first page
}


function BuyBoxCancel(){
    HideModalPopUp();
}

//Hide the Verify outfit message box when the continue button is clicked
//on the verify modal dialog box
function onVerifyOK(){
    $find(verifyOutfitBoxClientID).hide();  
}


function ShowRestartVerify(){
    $find(verifyRestartBoxID).show();
}


//Handles the start over button if the user chooses OK
function ResetOutfit(){
    Orvis.Outfitter.OutfitterService.ResetOutfit(outfitState, function(value){
        try{
            location.href = location.href;  //Reload the page
        }catch(e){
                HandlePageException(e);
        }
    }, FailedCallback);
}

///Handles the event of the buy box closing
function onOK(){

    //Add the entry to the outfit on the server object
    AddEntryToOutfit();
  
    
    //Clear out the current choice Values
    currentChoiceValues.ClearAllChoices();
    
}

//dummy but needed by asp.net ajax
function onAddToOutfitOK(){

}

   
//Adds the selected entry to the outfit.  If the add is OK, then build the selected entries
//list and set the innerHTML value
//Only builds the selected entries list of not in final review mode
function AddEntryToOutfit()
{
    var isMultiSelect = false;
    
    currentChoiceValues.SetAllChoiceValues();
    
    //Get the special Handling Responses
    spResponses = LoadSpecialHandlingResponses();
    
   //If the component is not multi-select and in normal mode, don't just add the entry, remove the current entries and then add this one
   //checking for the existence of the myComponents.GetComponentByID(outfitState.CurrentComponentID) will keep this from happening in
   //final review mode
   //First determine if this is a multi-select component
    if(outfitState.OutfitMode == OUTFIT_MODE_REVIEW){   
        isMultiSelect = mySelectedEntries.GetSelectedEntryByID(outfitState.CurrentEntryID).IsComponentMultiSelect;
    }else{
        isMultiSelect = myComponents.GetComponentByID(outfitState.CurrentComponentID).IsMultiSelect;
   } 
  
   if(!isMultiSelect){
        Orvis.Outfitter.OutfitterService.ReplaceEntryForNonMultiSelectComponent(outfitState, currentChoiceValues, spResponses, function(value){
            try{
               //If the add doesn't return a SelectedEntryItem then it's bad
               if(value)
               {    
                    var mySelectedEntryItem = value;
                   
                    //Currently the selected entries list is ony showing in normal mode
                    if(outfitState.OutfitMode == OUTFIT_MODE_NORMAL){    
                        mySelectedEntries.UpdateSelectedEntries(mySelectedEntryItem);
                    }else{
                        //Update this selected Entry in the internal selected entries list
                        //and update the list mode entry to reflect the new item
                        mySelectedEntries.UpdateInternalExistingSelectedEntry(mySelectedEntryItem);
                        myListMode.UpdateEntry(outfitState.LastEntryIDModifiedInReview);
                    }
                    
                    //Update the total
                    BuildSelectedEntriesTotal();
                    
               }
           }catch(e){
                    HandlePageException(e);
           }
           }, FailedCallback);
   } 
   else{
        Orvis.Outfitter.OutfitterService.AddEntryToOutfit(outfitState, currentChoiceValues, spResponses, function(value){
            try{
               //If the add doesn't return a SelectedEntryItem then it's bad
               if(value)
               {    
                    var mySelectedEntryItem = value;
                   
                    //Currently the selected entries list is ony showing in normal mode
                    if(outfitState.OutfitMode == OUTFIT_MODE_NORMAL){    
                        mySelectedEntries.UpdateSelectedEntries(mySelectedEntryItem);
                    }else{
                        //Update this selected Entry in the internal selected entries list
                        //and update the list mode entry to reflect the new item
                        mySelectedEntries.UpdateInternalExistingSelectedEntry(mySelectedEntryItem);
                        myListMode.UpdateEntry(outfitState.LastEntryIDModifiedInReview);
                    }
                    
                    //Update the total
                    BuildSelectedEntriesTotal();
                    
               }
           }catch(e){
                    HandlePageException(e);
           }
           }, FailedCallback);
    } 
}

//Handles the logic to check all of the entries in the outfit before adding them
//to the basket.  The add to basket will not be called if this call does not succeed
function VerifyOutfit(){
    Orvis.Outfitter.OutfitterService.VerifyOutfit(outfitState, function(value){
        try{
            //If the verify is OK, run the add to basket flow
            if(value){
                AddOutfitToBasket();
            }else{
                //Otherwise, show the verify error message and continue
                $find(verifyOutfitBoxClientID).show();  
            }
        }catch(e){
                HandlePageException(e);
        }
    }, FailedCallback);
}
//Adds all of the outfit items to the basket and redirects to the basket page
//if the add is successful
function AddOutfitToBasket()
{
    $find(addMessageBoxClientID).show();  
      
    try{
        //Adding the navigation information for CoreMetric tagging in the basket here
        //SDP 10-13-07
        Orvis.Outfitter.OutfitterService.AddOutfitToBasket(outfitState, 
                                        navigationState.dirID, 
                                        navigationState.groupID, 
                                        navigationState.catID, 
                                        navigationState.subCatID, 
                                        function(value){
            try{
                    location.href="basket.aspx";
            }catch(e){
                HandlePageException(e);
            }
        }, FailedCallback);
    }
    catch(err){
        LogClientCodeError("Error adding the outfit to the basket " + err.description);
    }
}
 

//Handles the event of an entry having it's "Add to outfit" button clicked
function EntryEdit(entryID){
    //Save the current outfit State as it is now selected
    outfitState.CurrentEntryID = entryID;
    
    var myEntry = myEntries.GetEntryByID(entryID);
    
    //If this is not a multi-selected component, then unselect all others visually
    if(!myComponents.GetComponentByID(outfitState.CurrentComponentID).IsMultiSelect){
        myEntries.VisuallyDeselectAllEntries();
    }
    //Mark this one visually
    myEntries.VisuallySelectEntry(entryID);
    
    
    //If this is the 'none' entry, remove all entries from this component
    if(entryID == NONE_ENTRY_ID){
        //Remove all of the entries for this component
        mySelectedEntries.RemoveAllEntriesForComponent(outfitState.CurrentSectionID, outfitState.CurrentComponentID,true);
        
        //Mark all of the components as unselected
        myEntries.VisuallyDeselectAllEntries();
        
        //Then mark the "none" entry as selected
        myEntries.VisuallySelectEntry(NONE_ENTRY_ID);
         //Rebuild the selected entries price
    }else{
        //If this is NOT the none entry
        
        //Deselect the "none" option now that something else has been chosen
        myEntries.VisuallyDeSelectEntry(NONE_ENTRY_ID);
        
        //process as normal
        if(myEntry.UsesBuyBox){
            OpenBuyBox(entryID);
        }else{
            AddEntryToOutfit();
        }
    }
}

//Handles the event of an entry being "selected" by the user
//the user still needs to get through the choices of the buybox before
//it can be added to the outfit
function OpenBuyBox(entryID)
{
    BuildBuyBox();
    ShowModalPopUp(); 
}


//Removes an entry from the outfit and manages the selected entries list
//by removing the selected node
function RemoveSelectedEntry(entryID, selectedEntryNodeID)
{
   //Remove from the local list and DOM
   mySelectedEntries.RemoveLocal(entryID, selectedEntryNodeID);
   
   //Remove from the server
   mySelectedEntries.Remove(entryID, selectedEntryNodeID);
    
    //also need to remove from the list mode view if it's showing
    if(outfitState.OutfitMode == OUTFIT_MODE_REVIEW){
        var myTempListMode = new ListMode();
        myTempListMode.RemoveEntryNode(entryID);
    }
}

//Sets off a chain reaction of asynch calls, look at the Edit method
//of the SelectedEntries object for more details
function EditSelectedEntry(sectionID, componentID, entryID, selectedEntryNodeID){
    mySelectedEntries.Edit(sectionID, componentID, entryID, selectedEntryNodeID);
}

//Load the initial data of the entry into the buybox
function BuildBuyBox()
{
    Orvis.Outfitter.OutfitterService.GetEntryDetails(outfitState, function(value){
        try{
            document.getElementById(CONTAINER_BUYBOX_DETAILS).innerHTML = value;
            currentChoiceValues.SetAllChoiceValues();
        }catch(e){
                HandlePageException(e);
        }
        }, FailedCallback);
        
    ShowWaitIndicator(CONTAINER_BUYBOX_DETAILS);
}

//Note: This only handles single special handling of type = textbox
//TODO - Make this handle other types and multiple types as well
function LoadSpecialHandlingResponses()
{
    var myResponses = new Array();
    
    //If there are any special handling prompts
    if($('SHPromptText1'))
    {
        var promptText = $('SHPromptText1').value;
        var promptValue = $('SHPrompt1').value;
        myResponses[0] = promptText + '|' +  promptValue;
    }
    
    return myResponses;
    
}

//Display the modal popup surrounding the buy box
function ShowModalPopUp()
{
    $find(buyBoxClientID).show();
}

function HideModalPopUp()
{
    $find(buyBoxClientID).hide();
}

function HideAnyModalPopup(popupID){
    $find(popupID).hide();
}

//Handles the select lists onchange event for choices.  Basically it picks the next 
//select list to target, gets the choice options for that select list given the previous
//choice values.  Loads that select list with this values
function choiceDataSelected(choiceValue, choiceID, isNotLastList)
{
    var defaultOptionText = '--Please Select--';
    var loadingMessage = 'loading...';
    
    var choiceValueID = "ChoiceValue" + choiceID
    
    currentChoiceValues[choiceValueID] = choiceValue;
    
    //Don't get the next choice values if there are none
    if(isNotLastList)
    {
        //For 3 and four choices when the choices have already been selected once
        //when the first is chosen, unset the values of the rest of the drop downs
        //to the default "please select" state
        var i = 1;
        while($('divChoice' + (parseInt(choiceID) + i))){
            //find the select list inside of this div
            var theSelect = $('selChoice' + (parseInt(choiceID) + i));
            //clear out all of the options
            for(var j = 0; j < theSelect.options.length; j++){
                theSelect.options[j] = null;
            }
            //add a new defaul option
            var defaultOption = new Option(defaultOptionText, -1);
            theSelect.options[0] = defaultOption;
            //increment the option counter
            i++;
        }
        var targetSelectID = "divChoice" + (parseInt(choiceID) + 1).toString();
        var promptText = $("selPrompt" + (parseInt(choiceID) + 1).toString()).innerHTML;
        
        //Mark this drop down as loading to indicate to the user that it's not ready
        $(targetSelectID).innerHTML = $(targetSelectID).innerHTML.replace(defaultOptionText, loadingMessage);
        
        Orvis.Outfitter.OutfitterService.GetEntryChoiceValues(outfitState, currentChoiceValues, choiceID, promptText, function(value){
            $(targetSelectID).innerHTML = value;
           //An IE Bug forces me to load the innerHTML of the div and not the select list
           //Otherwise I get <//Option> and other such junk
        }, FailedCallback);
    } 
}

//Handles the event when the "Final Review" tab is clicked.  Gets the SelectedEntries
//currently residing on the server and tells the ListMode object to build out the HTML
function CreateListMode(){
    
     Orvis.Outfitter.OutfitterService.GetSelectedEntries(outfitState, function(value){
        try{
            //Create a ListMode object
            myListMode = new ListMode(value, mySections);
            
            //Build the HTML for the ListMOde
            myListMode.BuildHTML();
            
            mySections.clickLock = false;  //turn off the click lock
        }catch(e){
                HandlePageException(e);
        }
    }, FailedCallback);
    
    //Show the wait indicator for selected entries
    var myTempListMode = new ListMode();    //without params, just want the utility functions
    myTempListMode.DisplayWaitIndicator();
    
    
    
}


//Switched the outfit mode from the normal view
//to the final review mode
function SwapOutfitMode(newMode){
    if(newMode == OUTFIT_MODE_NORMAL){
        $(CONTAINER_SELECTED_ENTRIES_LIST).className = 'summaryDetails';    //revert to the 'normal' selectedentries style
         outfitState.OutfitMode = OUTFIT_MODE_NORMAL;
        $('finalReviewTable').hide();
        $('contentTable').show();
        //On inital page load this isn't ready, i only
        //need this to work on a switch BACK from
        //final review mode anyway
        if(mySelectedEntries){
            mySelectedEntries.BuildHTML();
        }
        $('imgOutfitSoFar').show();
       
    }else{
    
       outfitState.OutfitMode = OUTFIT_MODE_REVIEW;
      $('contentTable').hide();
      //This will replace the selected entries list with a spacer gif with the same
      //dimensions to keep the screen from resizing all over when this is hidden
      //It used to be a function of the selectedEntries object but I pulled it out
      //as selectedEntries are not available yet when defaulting to ListMode (a new requirement)
      //This list will only be built in "Normal" mode, but the switch might happen after it's already built
      //If it was, then basically hide it here
      $(CONTAINER_SELECTED_ENTRIES_LIST).innerHTML = '';
      $(CONTAINER_SELECTED_ENTRIES_LIST).className = 'finalReviewSpacer';

      $('finalReviewTable').show();  
      $('imgOutfitSoFar').hide();
      
      //record a page view for coremetrics
      cmCreatePageviewTag(navigationState.buildPageParamString(), null, navigationState.buildNavParamString(), null, null);
      
    }
}

//Performs the logic for pricing and returns the correct display string
//This logic is needed in multiple places so I'm placing it here
function BuildPriceString(myEntry){
    var priceString = '';
    
    if(myEntry.HasStartingPrice){
        priceString = 'From ' + myEntry.Price;
    }else if(myEntry.HasSalePrice){
        priceString = '<span style="text-decoration: line-through">' + myEntry.Price + '</span>  Sale: ' + myEntry.SalePrice;
    }else{
        priceString = myEntry.Price;
    }
    
    return priceString;
}

//Generic function to handle and log failed server side calls
//That result in client side error messages
function FailedCallback(error)
{
    var stackTrace = error.get_stackTrace();
    var message = error.get_message();
    var statusCode = error.get_statusCode();
    var exceptionType = error.get_exceptionType();
    var timedout = error.get_timedOut();
   
    var errorMessage = 
        'Outfitter Server Side Callback Exception: \n' + 
        'Stack Trace: ' +  stackTrace + '\n' +
        'Service Error: ' + message + '\n' +
        'Status Code: ' + statusCode + '\n' +
        'Exception Type: ' + exceptionType + '\n' +
        'Timedout: ' + timedout + '\n';
        
   PrepareLogError(errorMessage);
        
}

//Formats a client error for logging and logs it for any unhandled page
//exception
//TODO - Use the prototype.caller property to build up a stack trace
function HandlePageError(errorMessage, url, lineNumber)
{
    var logMessage = 'Outfitter Client Side Exception: \n';
    
    logMessage += 'Message: ' + errorMessage + '\nURL: ' + url + '\nLineNumber: ' + lineNumber + '\n';
   
    PrepareLogError(logMessage); 
    
    return true;
}

//Used where window.onerror handling will not come into play
//Specifically callback methods in FireFox, using try/catch blocks instead
function HandlePageException(e){
    var stackTrace = e.stack;
    var fileName = e.fileName;
    var lineNumber = e.lineNumber;
    var name = e.name;
    var message = e.message;
    
   
    var errorMessage = 
        'Outfitter Server Side Callback Exception: \n' + 
        'Stack Trace: ' +  stackTrace + '\n' +
        'File Name: ' + fileName + '\n' +
        'Line Number: ' + lineNumber + '\n' +
        'Name: ' + name + '\n' +
        'Message: ' + message + '\n';
        
   PrepareLogError(errorMessage);
}

//Adds some outfitter specific messaging to the event to be logged
function PrepareLogError(errorMessage)
{
    var logMessage = 'Outfitter Error\n';
    logMessage += errorMessage + '\n';
    
    if(outfitState){
        logMessage += outfitState.Dump();
    }
  
   LogError(logMessage);
}

//Records error messages out to the server for logging and reporting
function LogError(errorMessage)
{
    errorMessage += BrowserDetect.BrowserLogString;
    
    Orvis.Outfitter.OutfitterService.LogClientError(errorMessage);
    
    //Let the user know there was an error
    DisplayErrorConsole();
    
    //Comment out unless debugging
    //alert(errorMessage);
}

//Display the wait indicator graphic in the given container
function ShowWaitIndicator(containerID)
{
    document.getElementById(containerID).innerHTML = '<img src="' + IMAGE_MAIN_THROBBER + '"/>';
}

//Show the message to let others know that this is being worked on
//It doesn't work on purpose...
function ShowUnImplemented(){
    alert('This feature is not yet implemented!');
}

//Clear the child nodes, used where I cannot call innerHTML = '' (like a table in IE)
function removeChildNodes(containerNode)
{
  while (containerNode.childNodes[0])
  {
    containerNode.removeChild(containerNode.childNodes[0]);
  }
}

//Opens a new browser window and sets focus
function ShowNewWindow(height, width, url)
{ 
	newWindow = window.open(url, 'OrvisHelpWindow_', 'toolbar=no,location=0,directories=no,status=no,menubar=0,scrollbars=yes,resizable=1,copyhistory=0, left=1, top=1,width=' + width + ',height=' + height);
	if(newWindow){
	    newWindow.focus();
	}
}
   
var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
		
		this.BrowserLogString = 'Browser ==> ' + this.browser + '\n' +
		                        'Version ==> ' + this.version + '\n' +
		                        'OS ==> ' + this.OS + '\n';
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();