IdenticalProductList(ProductLinksController controller, int[] product1_ids, int company2_id, Cliver.ProductIdentifier.Engine engine)
 {
     Product1Ids   = (from x in product1_ids where controller.db.Products.Where(p => p.Id == x).First().CompanyId != company2_id select x).ToArray();
     Company2Id    = company2_id;
     this.engine   = engine;
     product_links = engine.CreateProductLinkList(Product1Ids, Company2Id);
 }
            static IdenticalProductList get_from_session(ProductLinksController controller, int[] product1_ids, int company2_id)
            {
                IdenticalProductList ipl = (IdenticalProductList)controller.Session[IdenticalProductList.IdenticalProductList_SESSION_KEY];

                //IdenticalProductList ipl = (IdenticalProductList)System.Runtime.Caching.MemoryCache.Default.Get(IdenticalProductList.CacheKey);
                if (product1_ids == null)
                {
                    return(ipl);
                }
                if (ipl == null)
                {
                    ipl = new IdenticalProductList(controller, product1_ids, company2_id, new Cliver.ProductIdentifier.Engine(true));
                }
                else if (!ipl.is_corresponding(controller, product1_ids, company2_id))
                {
                    ipl = new IdenticalProductList(controller, product1_ids, company2_id, ipl.engine);
                }
                controller.Session[IdenticalProductList.IdenticalProductList_SESSION_KEY] = ipl;
                //System.Runtime.Caching.MemoryCache.Default.Set(IdenticalProductList.CacheKey, ipl, DateTimeOffset.Now.AddSeconds(3600));
                if (ipl.product_links.Count > 0 && ipl.product_links[0].Score > 1)
                {
                    ipl.ScoreFactor = 1D / ipl.product_links[0].Score;
                }
                return(ipl);
            }
            //const string Engine_SESSION_KEY = "IDENTICAL_PRODUCT_LIST";
            bool is_corresponding(ProductLinksController controller, int[] product1_ids, int company2_id)
            {
                if (Company2Id != company2_id)
                {
                    return(false);
                }

                Product p2 = controller.db.Products.Where(p => p.CompanyId == company2_id && product1_ids.Contains(p.Id)).FirstOrDefault();

                if (p2 != null)
                {
                    if (p2.LinkId > 0)
                    {
                        int[] p2_ids = controller.db.Products.Where(x => x.LinkId == p2.LinkId).Select(x => x.Id).ToArray();
                        product1_ids = product1_ids.Where(x => !p2_ids.Contains(x)).ToArray();
                    }
                    else
                    {
                        product1_ids = product1_ids.Where(x => x != p2.Id).ToArray();
                    }
                }
                if (!Product1Ids.OrderBy(x => x).SequenceEqual(product1_ids.OrderBy(x => x)))
                {
                    return(false);
                }
                return(true);
            }
            public static void SaveLink(ProductLinksController controller, int[] product_ids)
            {
                Cliver.ProductIdentifier.Engine engine;
                IdenticalProductList            ipl = get_from_session(controller, null, 0);

                if (ipl == null)
                {
                    engine = new Cliver.ProductIdentifier.Engine(true);
                }
                else
                {
                    engine = ipl.engine;
                }
                engine.SaveLink(product_ids);
            }
            public static IdenticalProductList GetMovingToNextRange(ProductLinksController controller, int[] product1_ids, int company2_id, string[] keyword2s, string category2, int range_size, bool forward, out bool is_CurrentProductLinks_changed)
            {
                product1_ids = product1_ids.Distinct().ToArray();

                IdenticalProductList ipl = get_from_session(controller, product1_ids, company2_id);

                ipl.set_pls_filtered(keyword2s, category2);
                is_CurrentProductLinks_changed = ipl.CurrentProductLinkRangeStartIndex == INITIAL_INDEX && ipl.CurrentProductLinkRangeEndIndex == INITIAL_INDEX;

                if (forward)
                {
                    ipl.CurrentProductLinkRangeStartIndex = ipl.CurrentProductLinkRangeEndIndex + 1;
                    ipl.CurrentProductLinkRangeEndIndex   = ipl.CurrentProductLinkRangeStartIndex + range_size - 1;
                    if (ipl.CurrentProductLinkRangeEndIndex >= ipl.CurrentProductLinks.Count)
                    {
                        ipl.CurrentProductLinkRangeEndIndex = ipl.CurrentProductLinks.Count - 1;
                    }
                    if (ipl.CurrentProductLinkRangeStartIndex >= ipl.CurrentProductLinks.Count)
                    {
                        ipl.CurrentProductLinkRangeStartIndex = ipl.CurrentProductLinks.Count;
                    }
                }
                else
                {
                    ipl.CurrentProductLinkRangeEndIndex   = ipl.CurrentProductLinkRangeStartIndex - 1;
                    ipl.CurrentProductLinkRangeStartIndex = ipl.CurrentProductLinkRangeEndIndex - range_size + 1;
                    if (ipl.CurrentProductLinkRangeStartIndex < 0)
                    {
                        ipl.CurrentProductLinkRangeStartIndex = 0;
                    }
                    if (ipl.CurrentProductLinkRangeEndIndex < 0)
                    {
                        ipl.CurrentProductLinkRangeEndIndex = -1;
                    }
                }
                return(ipl);
            }