// Processes the search calls from client: makes query to Amazon
        // (many if there are lots of results) while taking into account Amazon's
        // query limits.
        // GET: Amazon_Product_Surfer/Search
        public ActionResult Search(int page, string searchTerm, int isLast=0)
        {
            // Catch potential web exceptions that Amazon will return.
            try {
                string itemNameFromSearch;
                try
                {
                    itemNameFromSearch = Request.Form["Name"].ToString();
                }
                catch (NullReferenceException e)
                {
                    itemNameFromSearch = searchTerm;
                }
                int pageNumberOfOurSite = page;
                // Calculates which page to query.
                var pageAndItemToQuery = calculateQueryPage(pageNumberOfOurSite);
                int pageNumberForURL = pageAndItemToQuery.Item1;
                // Which item in the response would be the first in our chosen page.
                int itemIndexToStartFrom = pageAndItemToQuery.Item2;

                //This is the first query URL that queries for initial result.
                string URLString = generateRequestURL(itemNameFromSearch, pageNumberForURL, false, "");
                string URLstringDebug = URLString;

                XmlDocument xml = new XmlDocument();
                xml.Load(URLString);
                XmlNodeList xnListTitles = xml.GetElementsByTagName("Title");
                XmlNodeList xnListURLs = xml.GetElementsByTagName("DetailPageURL");
                XmlNodeList xnListIDs = xml.GetElementsByTagName("ASIN");
                XmlNodeList xnListTotal = xml.GetElementsByTagName("TotalResults");

                // How many items are there in total in Amazon's database.
                int totalQueryResults = int.Parse(xnListTotal[0].InnerText);

                // If there are items in the return we need to process them.
                if (xnListTitles.Count > 0)
                {
                    // Set a limit to the amount of items we can get.
                    int itemCount;

                    // Does the total amount of results limit preloaded page
                    if (totalQueryResults < 26)
                    {
                        // Does the current page set a limit
                        if (xnListTitles.Count < 10)
                        {
                            itemCount = xnListTitles.Count;
                        }
                        else
                        {
                            itemCount = totalQueryResults;
                        }
                    }
                    else
                    {
                        itemCount = 26;
                    }

                    string itemLookupCombo = "";

                    // Loop through the items and add them to our items list.
                    // If the item count reaches 10 and we have more left, we need to
                    // query amazon again.
                    for (int i = 0; i < itemCount; i++)
                    {
                        if (pageNumberForURL < 5)
                        {
                            // Makes a query every time it hits 10 items because of Amazon's limitation
                            // of 10 items per query.
                            if (itemIndexToStartFrom == 10)
                            {
                                // Reset response page item counter
                                itemIndexToStartFrom = 0;
                                // Increase the page we are looking to query from Amazon
                                pageNumberForURL += 1;
                                string URLString3 = generateRequestURL(itemNameFromSearch, pageNumberForURL, false, "");
                                XmlDocument xml3 = new XmlDocument();

                                xml3.Load(URLString3);

                                // Update the previous lists
                                xnListTitles = xml3.GetElementsByTagName("Title");
                                xnListURLs = xml3.GetElementsByTagName("DetailPageURL");
                                xnListIDs = xml3.GetElementsByTagName("ASIN");

                                // If the response has less elements than 10 we should stop adding items.
                                // Check if page returned less than 10 items and is it more or less than we have left to add.
                                int howManyElementsOnPage = xnListTitles.Count;
                                if (howManyElementsOnPage < 10 && (itemCount - i + 1) > howManyElementsOnPage)
                                {
                                    // Readjust the 26 item limit to fit the item amount we got as a response
                                    itemCount -= itemCount - i + 1 - howManyElementsOnPage;
                                }

                            }
                        }
                        else
                        {
                            break;
                        }
                        ItemFromAmazon item1 = new ItemFromAmazon(xnListIDs[itemIndexToStartFrom].InnerText, xnListTitles[itemIndexToStartFrom].InnerText,
                                                                    -1, -1, -1, -1, -1, -1, xnListURLs[itemIndexToStartFrom].InnerText);
                        itemIndexToStartFrom += 1;
                        itemsFromAmazon.Add(item1);
                    }

                    int elemCounter = 0;
                    int elementsLeft = itemsFromAmazon.Count;

                    // Query Amazon for Amazon's, new and used prices.
                    // Currently I couldn't find a XML format from them that
                    // Would give me all the info I need so I had to query again.
                    foreach (ItemFromAmazon element in itemsFromAmazon)
                    {
                        elemCounter += 1;
                        itemLookupCombo = itemLookupCombo + "%2C%20" + element.ID;

                        // After ten items query Amazon for prices and add them to our the items
                        // in Amazon item list.
                        if (elemCounter % 10 == 0)
                        {
                            URLString = generateRequestURL("", 0, true, itemLookupCombo);
                            elementsLeft -= 10;
                            XmlDocument xml2 = new XmlDocument();
                            xml2.Load(URLString);
                            XmlNodeList xnItems = xml2.GetElementsByTagName("Item");

                            for (int i = 0; i < xnItems.Count - 1; i++)
                            {
                                int ItemIndex = elemCounter - 10 + i;
                                // The fishcatching is to prepare for situations where there is nothing to sell
                                // in the category for which we are looking for the price.
                                if (xnItems[i]["OfferSummary"] != null)
                                {
                                    try
                                    {
                                        string priceNew = xnItems[i]["OfferSummary"]["LowestNewPrice"]["Amount"].InnerText;
                                        int priceNewForItem = int.Parse(priceNew);
                                        itemsFromAmazon[ItemIndex].priceNew = priceNewForItem;
                                        itemsFromAmazon[ItemIndex].priceNewF = (float)priceNewForItem / 100;
                                    }
                                    catch (NullReferenceException e)
                                    {
                                        itemsFromAmazon[ItemIndex].priceNew = -1;
                                        itemsFromAmazon[ItemIndex].priceNewF = -1;
                                    }

                                    try
                                    {
                                        string priceUsed = xnItems[i]["OfferSummary"]["LowestUsedPrice"]["Amount"].InnerText;
                                        int priceUsedForItem = int.Parse(priceUsed);
                                        itemsFromAmazon[ItemIndex].priceUsed = priceUsedForItem;
                                        itemsFromAmazon[ItemIndex].priceUsedF = (float)priceUsedForItem / 100;
                                    }
                                    catch (NullReferenceException e)
                                    {
                                        itemsFromAmazon[ItemIndex].priceUsed = -1;
                                        itemsFromAmazon[ItemIndex].priceUsedF = -1;
                                    }

                                }
                                else
                                {
                                    itemsFromAmazon[ItemIndex].priceNew = -1;
                                    itemsFromAmazon[ItemIndex].priceUsed = -1;
                                    itemsFromAmazon[ItemIndex].priceNewF = -1;
                                    itemsFromAmazon[ItemIndex].priceUsedF = -1;
                                }

                                try
                                {
                                    string priceAmazon = xnItems[i]["Offers"]["Offer"]["OfferListing"]["Price"]["Amount"].InnerText;
                                    int priceAmazonForItem = int.Parse(priceAmazon);
                                    itemsFromAmazon[ItemIndex].priceAmazon = priceAmazonForItem;
                                    itemsFromAmazon[ItemIndex].priceAmazonF = (float)priceAmazonForItem / 100;
                                }
                                catch (NullReferenceException e)
                                {
                                    itemsFromAmazon[ItemIndex].priceAmazon = -1;
                                    itemsFromAmazon[ItemIndex].priceAmazonF = -1;
                                }
                            }

                            itemLookupCombo = "";
                        }
                    }

                    // This part is for the leftover elements that do not reach 10.
                    if (elementsLeft > 0)
                    {
                        URLString = generateRequestURL("", 0, true, itemLookupCombo);
                        XmlDocument xml2 = new XmlDocument();
                        xml2.Load(URLString);
                        XmlNodeList xnItems = xml2.GetElementsByTagName("Item");

                        for (int i = 0; i < xnItems.Count - 1; i++)
                        {
                            int ItemIndex = elemCounter - elementsLeft + i;
                            if (xnItems[i]["OfferSummary"] != null)
                            {
                                try
                                {
                                    string priceNew = xnItems[i]["OfferSummary"]["LowestNewPrice"]["Amount"].InnerText;
                                    int priceNewForItem = int.Parse(priceNew);
                                    itemsFromAmazon[ItemIndex].priceNew = priceNewForItem;
                                    itemsFromAmazon[ItemIndex].priceNewF = (float)priceNewForItem / 100;
                                }
                                catch (NullReferenceException e)
                                {
                                    itemsFromAmazon[ItemIndex].priceNew = -1;
                                    itemsFromAmazon[ItemIndex].priceNewF = -1;
                                }

                                try
                                {
                                    string priceUsed = xnItems[i]["OfferSummary"]["LowestUsedPrice"]["Amount"].InnerText;
                                    int priceUsedForItem = int.Parse(priceUsed);
                                    itemsFromAmazon[ItemIndex].priceUsed = priceUsedForItem;
                                    itemsFromAmazon[ItemIndex].priceUsedF = (float)priceUsedForItem / 100;
                                }
                                catch (NullReferenceException e)
                                {
                                    itemsFromAmazon[ItemIndex].priceUsed = -1;
                                    itemsFromAmazon[ItemIndex].priceUsedF = -1;
                                }

                            }
                            else
                            {
                                itemsFromAmazon[ItemIndex].priceNew = -1;
                                itemsFromAmazon[ItemIndex].priceUsed = -1;
                                itemsFromAmazon[ItemIndex].priceNewF = -1;
                                itemsFromAmazon[ItemIndex].priceUsedF = -1;
                            }
                            try
                            {
                                string priceAmazon = xnItems[i]["Offers"]["Offer"]["OfferListing"]["Price"]["Amount"].InnerText;
                                int priceAmazonForItem = int.Parse(priceAmazon);
                                itemsFromAmazon[ItemIndex].priceAmazon = priceAmazonForItem;
                                itemsFromAmazon[ItemIndex].priceAmazonF = (float)priceAmazonForItem / 100;
                            }
                            catch (NullReferenceException e)
                            {
                                itemsFromAmazon[ItemIndex].priceAmazon = -1;
                                itemsFromAmazon[ItemIndex].priceAmazonF = -1;
                            }
                        }
                        itemLookupCombo = "";
                    }
                }
                if (totalQueryResults > 39)
                {
                    totalQueryResults = 39;
                }
                double totalQueryDouble = Convert.ToDouble(totalQueryResults);
                double amountOfPages = Math.Ceiling(totalQueryDouble / 13);

                ViewBag.AmounOfPages = Convert.ToInt32(amountOfPages);
                ViewBag.CurrentPage = Convert.ToInt32(pageNumberOfOurSite);
                ViewBag.Message2 = URLstringDebug;

                string[] currencies = new string[] { "USD", "EUR", "RUB" };

                ViewBag.codes = new SelectList(currencies);

                // Function for future reference (how to operate with jason and models).
                /*string url = "https://openexchangerates.org/api/latest.json?app_id=ce2cdca5548143c7b99a4ecdb2b0f4e1";
                WebClient client = new WebClient();
                String jsonData = client.DownloadString(url);

                dynamic data = JObject.Parse(jsonData);
                string jasonDataRates = data.rates.ToString();
                Rootobject exchangeRates = JsonConvert.DeserializeObject<Rootobject>(jasonDataRates);*/

                ViewModel toView = new ViewModel(itemsFromAmazon);
                toView.searchTerm = itemNameFromSearch;
                toView.page = page;
                toView.islast = isLast;
                toView.maxPages = Convert.ToInt32(amountOfPages);

                return View(toView);
            }
            catch (WebException e)
            {
                return RedirectToAction("Index", new { error=1 });
            }
        }
        String secretAccessKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // Insert Amazon secret access key.

        #endregion Fields

        #region Methods

        // This is the AJAX call that a page makes for the next page's content.
        // It's pretty much the same as main search action, with slight changes here and there.
        //[HttpPost]
        public PartialViewResult ajaxNewPage(int page, string searchTerm, string divToUpdate)
        {
            string itemNameFromSearch = "";
            itemNameFromSearch = searchTerm;

            int pageNumberOfOurSite = page;
            //Calculates which page to query
            var pageAndItemToQuery = calculateQueryPage(pageNumberOfOurSite);
            int pageNumberForURL = pageAndItemToQuery.Item1;
            //Which item in the response would be the first in our chosen page.
            int itemIndexToStartFrom = pageAndItemToQuery.Item2;

            string URLString = generateRequestURL(itemNameFromSearch, pageNumberForURL, false, ""); //This is the first query URL that queries for initial result.
            string URLstringDebug = URLString;

            XmlDocument xml = new XmlDocument();
            xml.Load(URLString);
            XmlNodeList xnListTitles = xml.GetElementsByTagName("Title");
            XmlNodeList xnListURLs = xml.GetElementsByTagName("DetailPageURL");
            XmlNodeList xnListIDs = xml.GetElementsByTagName("ASIN");
            XmlNodeList xnListTotal = xml.GetElementsByTagName("TotalResults");
            int totalQueryResults = int.Parse(xnListTotal[0].InnerText); //How many items are in total in Amazon's database

            if (xnListTitles.Count > 0)
            {
                int itemCount;// Set a limit to the amount of items we can get.

                if (totalQueryResults < 13) // Does the total amount of results limit preloaded page.
                {
                    if (xnListTitles.Count < 10) // Does the current page set a limit.
                    {
                        itemCount = xnListTitles.Count;
                    }
                    else
                    {
                        itemCount = totalQueryResults;
                    }
                }
                else
                {
                    itemCount = 13;
                }

                string itemLookupCombo = "";

                for (int i = 0; i < itemCount; i++)
                {
                    if (pageNumberForURL < 5)
                    {
                        // Makes a query every time it hits 10 items because of Amazon's limitation.
                        if (itemIndexToStartFrom == 10)
                        {
                            // Reset response page item counter
                            itemIndexToStartFrom = 0;
                            // Increase the page we are looking to query from Amazon
                            pageNumberForURL += 1;
                            string URLString3 = generateRequestURL(itemNameFromSearch, pageNumberForURL, false, "");
                            XmlDocument xml3 = new XmlDocument();
                            xml3.Load(URLString3);
                            // Update the previous lists
                            xnListTitles = xml3.GetElementsByTagName("Title");
                            xnListURLs = xml3.GetElementsByTagName("DetailPageURL");
                            xnListIDs = xml3.GetElementsByTagName("ASIN");
                            // If the response has less elements than 10 we should stop adding items
                            // Check if page returned less than 10 items and is it more or less than we have left to add
                            int howManyElementsOnPage = xnListTitles.Count;
                            if (howManyElementsOnPage < 10 && (itemCount - i + 1) > howManyElementsOnPage)
                            {
                                // Readjust the 26 item limit to fit the item amount we got as a response
                                itemCount -= itemCount - i + 1 - howManyElementsOnPage;
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                    ItemFromAmazon item1 = new ItemFromAmazon(xnListIDs[itemIndexToStartFrom].InnerText, xnListTitles[itemIndexToStartFrom].InnerText,
                                                                -1, -1, -1, -1, -1, -1, xnListURLs[itemIndexToStartFrom].InnerText);
                    itemIndexToStartFrom += 1;
                    itemsFromAmazon.Add(item1);
                }

                int elemCounter = 0;
                int elementsLeft = itemsFromAmazon.Count;

                // Query Amazon for Amazon's, new and used prices.
                // Currently I couldn't find a XML format from them that
                // Would give me all the info I need so I had to query again.
                foreach (ItemFromAmazon element in itemsFromAmazon)
                {
                    elemCounter += 1;
                    itemLookupCombo = itemLookupCombo + "%2C%20" + element.ID;

                    // After ten items query Amazon for prices and add them to our the items
                    // in Amazon item list.
                    if (elemCounter % 10 == 0)
                    {

                        URLString = generateRequestURL("", 0, true, itemLookupCombo);
                        elementsLeft -= 10;
                        XmlDocument xml2 = new XmlDocument();
                        xml2.Load(URLString);
                        XmlNodeList xnItems = xml2.GetElementsByTagName("Item");

                        for (int i = 0; i < xnItems.Count - 1; i++)
                        {
                            int ItemIndex = elemCounter - 10 + i;
                            if (xnItems[i]["OfferSummary"] != null)
                            {
                                // The fishcatching is to prepare for situations where there is nothing to sell
                                // in the category for which we are looking for the price.
                                try
                                {
                                    string priceNew = xnItems[i]["OfferSummary"]["LowestNewPrice"]["Amount"].InnerText;
                                    int priceNewForItem = int.Parse(priceNew);
                                    itemsFromAmazon[ItemIndex].priceNew = priceNewForItem;
                                    itemsFromAmazon[ItemIndex].priceNewF = (float)priceNewForItem / 100;
                                }
                                catch (NullReferenceException e)
                                {
                                    itemsFromAmazon[ItemIndex].priceNew = -1;
                                    itemsFromAmazon[ItemIndex].priceNewF = -1;
                                }

                                try
                                {
                                    string priceUsed = xnItems[i]["OfferSummary"]["LowestUsedPrice"]["Amount"].InnerText;
                                    int priceUsedForItem = int.Parse(priceUsed);
                                    itemsFromAmazon[ItemIndex].priceUsed = priceUsedForItem;
                                    itemsFromAmazon[ItemIndex].priceUsedF = (float)priceUsedForItem / 100;
                                }
                                catch (NullReferenceException e)
                                {
                                    itemsFromAmazon[ItemIndex].priceUsed = -1;
                                    itemsFromAmazon[ItemIndex].priceUsedF = -1;
                                }

                            }
                            else
                            {
                                itemsFromAmazon[ItemIndex].priceNew = -1;
                                itemsFromAmazon[ItemIndex].priceUsed = -1;
                                itemsFromAmazon[ItemIndex].priceNewF = -1;
                                itemsFromAmazon[ItemIndex].priceUsedF = -1;
                            }

                            try
                            {
                                string priceAmazon = xnItems[i]["Offers"]["Offer"]["OfferListing"]["Price"]["Amount"].InnerText;
                                int priceAmazonForItem = int.Parse(priceAmazon);
                                itemsFromAmazon[ItemIndex].priceAmazon = priceAmazonForItem;
                                itemsFromAmazon[ItemIndex].priceAmazonF = (float)priceAmazonForItem / 100;
                            }
                            catch (NullReferenceException e)
                            {
                                itemsFromAmazon[ItemIndex].priceAmazon = -1;
                                itemsFromAmazon[ItemIndex].priceAmazonF = -1;
                            }
                        }

                        itemLookupCombo = "";
                    }
                }

                if (elementsLeft > 0)
                {
                    URLString = generateRequestURL("", 0, true, itemLookupCombo);
                    XmlDocument xml2 = new XmlDocument();
                    xml2.Load(URLString);
                    XmlNodeList xnItems = xml2.GetElementsByTagName("Item");

                    for (int i = 0; i < xnItems.Count - 1; i++)
                    {
                        int ItemIndex = elemCounter - elementsLeft + i;
                        if (xnItems[i]["OfferSummary"] != null)
                        {
                            try
                            {
                                string priceNew = xnItems[i]["OfferSummary"]["LowestNewPrice"]["Amount"].InnerText;
                                int priceNewForItem = int.Parse(priceNew);
                                itemsFromAmazon[ItemIndex].priceNew = priceNewForItem;
                                itemsFromAmazon[ItemIndex].priceNewF = (float)priceNewForItem / 100;
                            }
                            catch (NullReferenceException e)
                            {
                                itemsFromAmazon[ItemIndex].priceNew = -1;
                                itemsFromAmazon[ItemIndex].priceNewF = -1;
                            }

                            try
                            {
                                string priceUsed = xnItems[i]["OfferSummary"]["LowestUsedPrice"]["Amount"].InnerText;
                                int priceUsedForItem = int.Parse(priceUsed);
                                itemsFromAmazon[ItemIndex].priceUsed = priceUsedForItem;
                                itemsFromAmazon[ItemIndex].priceUsedF = (float)priceUsedForItem / 100;
                            }
                            catch (NullReferenceException e)
                            {
                                itemsFromAmazon[ItemIndex].priceUsed = -1;
                                itemsFromAmazon[ItemIndex].priceUsedF = -1;
                            }

                        }
                        else
                        {
                            itemsFromAmazon[ItemIndex].priceNew = -1;
                            itemsFromAmazon[ItemIndex].priceUsed = -1;
                            itemsFromAmazon[ItemIndex].priceNewF = -1;
                            itemsFromAmazon[ItemIndex].priceUsedF = -1;
                        }
                        try
                        {
                            string priceAmazon = xnItems[i]["Offers"]["Offer"]["OfferListing"]["Price"]["Amount"].InnerText;
                            int priceAmazonForItem = int.Parse(priceAmazon);
                            itemsFromAmazon[ItemIndex].priceAmazon = priceAmazonForItem;
                            itemsFromAmazon[ItemIndex].priceAmazonF = (float)priceAmazonForItem / 100;
                        }
                        catch (NullReferenceException e)
                        {
                            itemsFromAmazon[ItemIndex].priceAmazon = -1;
                            itemsFromAmazon[ItemIndex].priceAmazonF = -1;
                        }
                    }
                    itemLookupCombo = "";
                }
            }
            if (totalQueryResults > 39)
            {
                totalQueryResults = 39;
            }
            double totalQueryDouble = Convert.ToDouble(totalQueryResults);
            double amountOfPages = Math.Ceiling(totalQueryDouble / 13);

            ViewBag.AmounOfPages = Convert.ToInt32(amountOfPages);
            ViewBag.CurrentPage = Convert.ToInt32(pageNumberOfOurSite);
            ViewBag.Message2 = divToUpdate;

            ViewModel toView2 = new ViewModel(itemsFromAmazon);
            toView2.searchTerm = itemNameFromSearch;
            toView2.page = page;

            return PartialView("NextPageSearch", toView2);
        }