using System;
using NorthwindAPI.DataLayer;
using System.Collections.Generic;
using System.Threading.Tasks;
 
namespace NorthwindAPI.BusinessObject.Base
{
     /// <summary>
     /// Base class for Products.  Do not make changes to this class,
     /// instead, put additional code in the Products (parent) class.
     /// </summary>
     public class ProductsBase : NorthwindAPI.Models.ProductsModel
     {
         /// <summary>
         /// Gets or sets the Related Suppliers.  Related to column SupplierID
         /// </summary>
         public Lazy<Task<Suppliers>> Suppliers
         {
             get
             {
                 if (this?.SupplierID != null) 
                    return new Lazy<Task<Suppliers>>(async () => await BusinessObject.Suppliers.SelectByPrimaryKeyAsync(SupplierID.Value));
 
                 return null;
             }
             set{ }
         } 
 
         /// <summary>
         /// Gets or sets the Related Categories.  Related to column CategoryID
         /// </summary>
         public Lazy<Task<Categories>> Categories
         {
             get
             {
                 if (this?.CategoryID != null) 
                    return new Lazy<Task<Categories>>(async () => await BusinessObject.Categories.SelectByPrimaryKeyAsync(CategoryID.Value));
 
                 return null;
             }
             set{ }
         } 
 
 
         /// <summary>
         /// Constructor
         /// </summary>
         public ProductsBase()
         {
         }
 
         /// <summary>
         /// Selects a record by primary key(s)
         /// </summary>
         public static async Task<Products> SelectByPrimaryKeyAsync(int productID)
         {
             return await ProductsDataLayer.SelectByPrimaryKeyAsync(productID);
         }
 
         /// <summary>
         /// Gets the total number of records in the Products table
         /// </summary>
         public static async Task<int> GetRecordCountAsync()
         {
             return await ProductsDataLayer.GetRecordCountAsync();
         }
 
         /// <summary>
         /// Gets the total number of records in the Products table by SupplierID
         /// </summary>
         public static async Task<int> GetRecordCountBySupplierIDAsync(int? supplierID)
         {
             return await ProductsDataLayer.GetRecordCountBySupplierIDAsync(supplierID);
         }
 
         /// <summary>
         /// Gets the total number of records in the Products table by CategoryID
         /// </summary>
         public static async Task<int> GetRecordCountByCategoryIDAsync(int? categoryID)
         {
             return await ProductsDataLayer.GetRecordCountByCategoryIDAsync(categoryID);
         }
 
         /// <summary>
         /// Gets the total number of records in the Products table based on search parameters
         /// </summary>
         public static async Task<int> GetRecordCountDynamicWhereAsync(int? productID, string productName, int? supplierID, int? categoryID, string quantityPerUnit, decimal? unitPrice, Int16? unitsInStock, Int16? unitsOnOrder, Int16? reorderLevel, bool? discontinued)
         {
             return await ProductsDataLayer.GetRecordCountDynamicWhereAsync(productID, productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued);
         }
 
         /// <summary>
         /// Selects records as a collection (List) of Products sorted by the sortByExpression.
         /// </summary>
         public static async Task<List<Products>> SelectSkipAndTakeAsync(int rows, int startRowIndex, string sortByExpression)
         {
             sortByExpression = GetSortExpression(sortByExpression);
             return await ProductsDataLayer.SelectSkipAndTakeAsync(sortByExpression, startRowIndex, rows);
         }
 
         /// <summary>
         /// Selects records by SupplierID as a collection (List) of Products sorted by the sortByExpression starting from the startRowIndex
         /// </summary>
         public static async Task<List<Products>> SelectSkipAndTakeBySupplierIDAsync(int rows, int startRowIndex, string sortByExpression, int? supplierID)
         {
             sortByExpression = GetSortExpression(sortByExpression);
             return await ProductsDataLayer.SelectSkipAndTakeBySupplierIDAsync(sortByExpression, startRowIndex, rows, supplierID);
         }
 
         /// <summary>
         /// Selects records by CategoryID as a collection (List) of Products sorted by the sortByExpression starting from the startRowIndex
         /// </summary>
         public static async Task<List<Products>> SelectSkipAndTakeByCategoryIDAsync(int rows, int startRowIndex, string sortByExpression, int? categoryID)
         {
             sortByExpression = GetSortExpression(sortByExpression);
             return await ProductsDataLayer.SelectSkipAndTakeByCategoryIDAsync(sortByExpression, startRowIndex, rows, categoryID);
         }
 
         /// <summary>
         /// Selects records as a collection (List) of Products sorted by the sortByExpression starting from the startRowIndex, based on the search parameters
         /// </summary>
         public static async Task<List<Products>> SelectSkipAndTakeDynamicWhereAsync(int? productID, string productName, int? supplierID, int? categoryID, string quantityPerUnit, decimal? unitPrice, Int16? unitsInStock, Int16? unitsOnOrder, Int16? reorderLevel, bool? discontinued, int rows, int startRowIndex, string sortByExpression)
         {
             sortByExpression = GetSortExpression(sortByExpression);
             return await ProductsDataLayer.SelectSkipAndTakeDynamicWhereAsync(productID, productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued, sortByExpression, startRowIndex, rows);
         }
 
         /// <summary>
         /// Selects all records as a collection (List) of Products
         /// </summary>
         public static async Task<List<Products>> SelectAllAsync()
         {
             return await ProductsDataLayer.SelectAllAsync();
         }
 
         /// <summary>
         /// Selects all records as a collection (List) of Products sorted by the sort expression
         /// </summary>
         public static async Task<List<Products>> SelectAllAsync(string sortByExpression)
         {
             List<Products> objProductsCol = await ProductsDataLayer.SelectAllAsync();
             return await SortByExpressionAsync(objProductsCol, sortByExpression);
         }
 
         /// <summary>
         /// Selects records based on the passed filters as a collection (List) of Products.
         /// </summary>
         public static async Task<List<Products>> SelectAllDynamicWhereAsync(int? productID, string productName, int? supplierID, int? categoryID, string quantityPerUnit, decimal? unitPrice, Int16? unitsInStock, Int16? unitsOnOrder, Int16? reorderLevel, bool? discontinued)
         {
             return await ProductsDataLayer.SelectAllDynamicWhereAsync(productID, productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued);
         }
 
         /// <summary>
         /// Selects records based on the passed filters as a collection (List) of Products sorted by the sort expression.
         /// </summary>
         public static async Task<List<Products>> SelectAllDynamicWhereAsync(int? productID, string productName, int? supplierID, int? categoryID, string quantityPerUnit, decimal? unitPrice, Int16? unitsInStock, Int16? unitsOnOrder, Int16? reorderLevel, bool? discontinued, string sortByExpression)
         {
             List<Products> objProductsCol = await ProductsDataLayer.SelectAllDynamicWhereAsync(productID, productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued);
             return await SortByExpressionAsync(objProductsCol, sortByExpression);
         }
 
         /// <summary>
         /// Selects ProductID and ProductName columns for use with a DropDownList web control, ComboBox, CheckedBoxList, ListView, ListBox, etc
         /// </summary>
         public static async Task<List<Products>> SelectProductsDropDownListDataAsync()
         {
             return await ProductsDataLayer.SelectProductsDropDownListDataAsync();
         }
 
         /// <summary>
         /// Sorts the List<Products >by sort expression
         /// </summary>
         public static async Task<List<Products>> SortByExpressionAsync(List<Products> objProductsCol, string sortExpression)
         {
             bool isSortDescending = sortExpression.ToLower().Contains(" desc");
 
             if (isSortDescending)
             {
                 sortExpression = sortExpression.Replace(" DESC""");
                 sortExpression = sortExpression.Replace(" desc""");
             }
             else
             {
                 sortExpression = sortExpression.Replace(" ASC""");
                 sortExpression = sortExpression.Replace(" asc""");
             }
 
             switch (sortExpression)
             {
                 case "ProductID":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByProductID));
                     break;
                 case "ProductName":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByProductName));
                     break;
                 case "SupplierID":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.BySupplierID));
                     break;
                 case "CategoryID":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByCategoryID));
                     break;
                 case "QuantityPerUnit":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByQuantityPerUnit));
                     break;
                 case "UnitPrice":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByUnitPrice));
                     break;
                 case "UnitsInStock":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByUnitsInStock));
                     break;
                 case "UnitsOnOrder":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByUnitsOnOrder));
                     break;
                 case "ReorderLevel":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByReorderLevel));
                     break;
                 case "Discontinued":
                     await Task.Run(() => objProductsCol.Sort(NorthwindAPI.BusinessObject.Products.ByDiscontinued));
                     break;
                 default:
                     break;
             }
 
             if (isSortDescending)
                 objProductsCol.Reverse();
 
             return objProductsCol;
         }
 
         /// <summary>
         /// Inserts a record
         /// </summary>
         public async Task<int> InsertAsync()
         {
             Products objProducts = (Products)this;
             return await ProductsDataLayer.InsertAsync(objProducts);
         }
 
         /// <summary>
         /// Updates a record
         /// </summary>
         public async Task UpdateAsync()
         {
             Products objProducts = (Products)this;
             await ProductsDataLayer.UpdateAsync(objProducts);
         }
 
         /// <summary>
         /// Deletes a record based on primary key(s)
         /// </summary>
         public static async Task DeleteAsync(int productID)
         {
             await Task.Run(() => ProductsDataLayer.DeleteAsync(productID));
         }
 
         /// <summary>
         /// Deletes multiple records based on primary keys
         /// </summary>
         public static async Task DeleteMultipleAsync(List<Int32> productIDList)
         {
             foreach (var id in productIDList)
             {
                 await ProductsDataLayer.DeleteAsync(id);
             }
         }
 
         /// <summary>
         /// Gets the default sort expression when no sort expression is provided
         /// </summary>
         private static string GetSortExpression(string sortByExpression)
         {
             // when no sort expression is provided, ProductID is set as the default in ascending order
             // for ascending order, "asc" is not needed, so it is removed
             if (String.IsNullOrEmpty(sortByExpression) || sortByExpression == " asc")
                 sortByExpression = "ProductID";
             else if (sortByExpression.Contains(" asc"))
                 sortByExpression = sortByExpression.Replace(" asc""");
 
             return sortByExpression;
         }
 
         /// <summary>
         /// Compares ProductID used for sorting
         /// </summary>
         public static Comparison<Products> ByProductID = delegate(Products x, Products y)
         {
             return x.ProductID.CompareTo(y.ProductID);
         };
 
         /// <summary>
         /// Compares ProductName used for sorting
         /// </summary>
         public static Comparison<Products> ByProductName = delegate(Products x, Products y)
         {
             string value1 = x.ProductName ?? String.Empty;
             string value2 = y.ProductName ?? String.Empty;
             return value1.CompareTo(value2);
         };
 
         /// <summary>
         /// Compares SupplierID used for sorting
         /// </summary>
         public static Comparison<Products> BySupplierID = delegate(Products x, Products y)
         {
             return Nullable.Compare(x.SupplierID, y.SupplierID);
         };
 
         /// <summary>
         /// Compares CategoryID used for sorting
         /// </summary>
         public static Comparison<Products> ByCategoryID = delegate(Products x, Products y)
         {
             return Nullable.Compare(x.CategoryID, y.CategoryID);
         };
 
         /// <summary>
         /// Compares QuantityPerUnit used for sorting
         /// </summary>
         public static Comparison<Products> ByQuantityPerUnit = delegate(Products x, Products y)
         {
             string value1 = x.QuantityPerUnit ?? String.Empty;
             string value2 = y.QuantityPerUnit ?? String.Empty;
             return value1.CompareTo(value2);
         };
 
         /// <summary>
         /// Compares UnitPrice used for sorting
         /// </summary>
         public static Comparison<Products> ByUnitPrice = delegate(Products x, Products y)
         {
             return Nullable.Compare(x.UnitPrice, y.UnitPrice);
         };
 
         /// <summary>
         /// Compares UnitsInStock used for sorting
         /// </summary>
         public static Comparison<Products> ByUnitsInStock = delegate(Products x, Products y)
         {
             return Nullable.Compare(x.UnitsInStock, y.UnitsInStock);
         };
 
         /// <summary>
         /// Compares UnitsOnOrder used for sorting
         /// </summary>
         public static Comparison<Products> ByUnitsOnOrder = delegate(Products x, Products y)
         {
             return Nullable.Compare(x.UnitsOnOrder, y.UnitsOnOrder);
         };
 
         /// <summary>
         /// Compares ReorderLevel used for sorting
         /// </summary>
         public static Comparison<Products> ByReorderLevel = delegate(Products x, Products y)
         {
             return Nullable.Compare(x.ReorderLevel, y.ReorderLevel);
         };
 
         /// <summary>
         /// Compares Discontinued used for sorting
         /// </summary>
         public static Comparison<Products> ByDiscontinued = delegate(Products x, Products y)
         {
             return x.Discontinued.CompareTo(y.Discontinued);
         };
 
     }
}