using OnlineSalesAutoCrop.CoreAPI.Models.Objects.Systems;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;

namespace OnlineSalesAutoCrop.CoreAPI.Models.Global
{
	public static class GlobalFunctions
	{
		#region Menu Related Functions

		/// <summary>
		/// 
		/// </summary>
		/// <param name="parent"></param>
		/// <param name="srcData"></param>
		private static void MakeHierarchy(GroupPermission parent, List<GroupPermission> srcData)
		{
			try
			{
				IEnumerable<GroupPermission> children = srcData.Where(x => x.ParentId == parent.ModuleId);
				parent.Children.AddRange(children);
				foreach (GroupPermission child in parent.Children)
				{
					MakeHierarchy(parent: child, srcData: srcData);
				}
			}
			catch (Exception e)
			{
				throw new InvalidOperationException(e.Message, e);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public static Menu HierarchicalMenu()
		{
			Menu menu = [];

			Menu flatMenu = BuildMenu();
			IEnumerable<GroupPermission> data = flatMenu.Where(x => string.IsNullOrEmpty(x.ParentId) || string.IsNullOrWhiteSpace(x.ParentId));
			menu.AddRange(data);

			foreach (GroupPermission parent in menu)
			{
				MakeHierarchy(parent: parent, srcData: flatMenu);
			}

			return menu;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		public static Menu BuildMenu()
		{
			Menu menu = [];

			#region System Setup

			menu.BeginGroup("ELIT.1", "System Setup", "fa fa-sun-o");
			menu.MenuItem("ELIT.1.3", "Label Setting", "fa fa-sliders", "labelsetting", true);
			menu.MenuItem("ELIT.1.1", "System Information", "fa fa-cog", "thissystem", true);
			menu.MenuItem("ELIT.1.1A", "Sales Dashboard", false);
			menu.MenuItem("ELIT.1.1B", "Accounting Dashboard", false);
			menu.MenuItem("ELIT.1.1C", "Purchase Dashboard", false);
			menu.MenuItem("ELIT.1.1D", "Fixed Assets Dashboard", false);

			menu.BeginGroup("ELIT.1.2", "User Management", "fa fa-users");
			menu.MenuItem("ELIT.1.2.1", "Groups", "fa fa-address-book-o", "groups", true);
			menu.MenuItem("ELIT.1.2.2", "Users", "fa fa-address-card-o", "users", true);
			menu.MenuItem("ELIT.1.2.3", "Reset Password", false);
			menu.MenuItem("ELIT.1.2.4", "Force Logout", "fa fa-address-card-o", "forcelogout", true);
			menu.MenuItem("ELIT.1.2.5", "View Other's Access log", false);
			menu.EndGroup();

			menu.MenuItem("ELIT.1.3A", "Lookup Data", "fa fa-sliders", "lookupdata", true);
			menu.MenuItem("ELIT.1.4", "Custom Report Setup", "fa fa-table", "customreports", true);

			menu.BeginGroup("ELIT.1.5", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.1.5.1", "Clients", "fa fa-address-card-o", "clients", true);
			menu.MenuItem("ELIT.1.5.2", "Suppliers", "fa fa-credit-card", "suppliers", true);
			menu.MenuItem("ELIT.1.5.2A", "Allow to Set Cash Purchase Suppliers", false);
			menu.MenuItem("ELIT.1.5.3", "Employees", "fa fa-user-plus", "employees", true);
			menu.MenuItem("ELIT.1.5.4", "Project Leads", "fa fa-user-circle-o", "projectleads", true);
			menu.MenuItem("ELIT.1.5.5", "Project Managers", "fa fa-user-circle-o", "projectmgts", true);
			menu.MenuItem("ELIT.1.5.6", "Projects", "fa fa-product-hunt", "projects", true);
			menu.MenuItem("ELIT.1.5.7", "Stores", "fa fa-pencil-square", "stores", true);
			menu.MenuItem("ELIT.1.5.7A", "Allow to Set Central Store", false);
			menu.MenuItem("ELIT.1.5.8", "Banks & Branches", "fa fa-university", "bankbranches", true);
			menu.MenuItem("ELIT.1.5.9", "Bank Accounts", "fa fa-credit-card", "bankaccounts", true);
			menu.MenuItem("ELIT.1.5.10", "GL Codes", "fa fa-book", "glcodes", true);
			menu.MenuItem("ELIT.1.5.11", "User Clients & Projects", "fa fa-product-hunt", "userprojects", true);
			menu.MenuItem("ELIT.1.5.12", "User Suppliers", "fa fa-product-hunt", "usersuppliers", true);
			menu.MenuItem("ELIT.1.5.15", "Edit Code (All Setups)", false);
			menu.EndGroup();

			menu.EndGroup();

			#endregion

			#region Athentication Process

			menu.BeginGroup("ELIT.2", "Authentication Process", "fa fa-cogs");
			menu.MenuItem("ELIT.2.1", "Authentication", "fa fa-check", "authentications", true);
			menu.MenuItem("ELIT.2.2", "Authorization", "fa fa-check-square-o", "authorizations", true);
			menu.MenuItem("ELIT.2.3", "Deactivation", "fa fa-window-close-o", "deactivations", true);
			menu.MenuItem("ELIT.2.4", "Pending Authentication", string.Empty, "pendingauth", false);
			menu.EndGroup();

			#endregion

			#region General Ledger

			menu.BeginGroup("ELIT.3", "General Ledger", "fa fa-university");

			menu.BeginGroup("ELIT.3.1", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.3.1.1", "Chart of Accounts", "fa fa-th-list", "chartofaccounts", true);
			menu.MenuItem("ELIT.3.1.2", "Fix GL Balance", "fa fa-wrench", "fixBalance", true);
			menu.MenuItem("ELIT.3.1.3", "GL Head Identification", "fa fa-cog", "identifyglhead", true);
			menu.EndGroup();

			menu.BeginGroup("ELIT.3.2", "Transactions", "fa fa-building");
			menu.MenuItem("ELIT.3.2.1", "GL Transactions", "fa fa-archive", "gltrans", true);
			menu.MenuItem("ELIT.3.2.2", "Upload Auto Voucher", "fa fa-upload", "gltranav", true);
			menu.MenuItem("ELIT.3.2.3", "Year End Process", "fa fa-cog", "yearendprocess", true);
			menu.MenuItem("ELIT.3.2.4", "Undo Year End", "fa fa-undo", "undoyearend", true);
			menu.MenuItem("ELIT.3.2.5", "Authorize Transactions", "fa fa-check-square", "authgltrans", true);
			menu.MenuItem("ELIT.3.2.6", "Special Delete of GL Transaction", false);
			menu.MenuItem("ELIT.3.2.7", "Rollback Transactions", "fa fa-undo", "rollbackgltrans", true);
			menu.MenuItem("ELIT.3.2.8", "Dashboard Processor", "fa fa-cog", "dbprocessor", true);
			menu.EndGroup();

			menu.BeginGroup("ELIT.3.3", "Reports", "fa fa-newspaper-o");
			menu.MenuItem("ELIT.3.3.1", "Ledger", "fa fa-file-text-o", "glledger", true);
			menu.MenuItem("ELIT.3.3.2", "Monthly Turnover", "fa fa-file-text-o", "turnover", true);
			menu.MenuItem("ELIT.3.3.3", "Trial Balance", "fa fa-file-text-o", "trialbalance", true);
			menu.MenuItem("ELIT.3.3.8", "Income & Expenditure", "fa fa-file-text-o", "incomeexpense", true);
			menu.MenuItem("ELIT.3.3.4", "Day Book", "fa fa-file-text-o", "daybook", true);
			menu.MenuItem("ELIT.3.3.5", "Bank/Cash Book", "fa fa-file-text-o", "bankcashbook", true);
			menu.MenuItem("ELIT.3.3.6", "Schedule", "fa fa-file-text-o", "glschedule", true);
			menu.MenuItem("ELIT.3.3.7", "Previous Final Reports", "fa fa-file-text-o", "prvfinalreports", true);
			menu.EndGroup();

			menu.EndGroup();

			#endregion

			#region Order To Cash

			menu.BeginGroup("ELIT.4", "Order To Cash", "fa fa-money");

			menu.BeginGroup("ELIT.4.1", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.4.1.1", "Income GL Codes", "fa fa-pencil-square-o", "incomeglcodes", true);
			menu.MenuItem("ELIT.4.1.2", "VAT Liability GL Codes", "fa fa-pencil-square", "vatglcodes", true);
			menu.MenuItem("ELIT.4.1.3", "AIT GL Codes", "fa fa-book", "aitglcodes", true);
			menu.MenuItem("ELIT.4.1.10", "Edit Code (All Setups)", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.4.2", "Regular Activities", "fa fa-building");
			menu.MenuItem("ELIT.4.2.1", "Purchase Orders", "fa fa-smile-o", "purchaseorders", true);
			menu.MenuItem("ELIT.4.2.2", "Invoices", "fa fa-share-square", "invoices", true);
			menu.MenuItem("ELIT.4.2.3", "Payments", "fa fa-money", "payments", true);
			menu.MenuItem("ELIT.4.2.4", "Freeze PO/Invoice", "fa fa-archive", "archivepoinvs", true);
			menu.MenuItem("ELIT.4.2.5", "PO Attachment", false);
			menu.MenuItem("ELIT.4.2.6", "Payment Confirmation", false);
			menu.MenuItem("ELIT.4.2.7", "Special Edit of PO/Invoice", false);
			menu.MenuItem("ELIT.4.2.8", "VAT Challan Update", "fa fa-sliders", "updvatchlano2c", true);
			menu.EndGroup();

			menu.BeginGroup("ELIT.4.3", "Reports", "fa fa-newspaper-o");
			menu.MenuItem("ELIT.4.3.1", "GL Vouchers", "fa fa-th-list", "glvouchers", true);
			menu.MenuItem("ELIT.4.3.2", "Transactional Reports", "fa fa-file-text-o", "txnreports", true);
			menu.MenuItem("ELIT.4.3.3", "Contract Expiry Report", "fa fa-file-text-o", "contexpryreports", true);
			menu.MenuItem("ELIT.4.3.4", "Customized Report", "fa fa-file-text-o", "customreporto2c", true);
			menu.MenuItem("ELIT.4.3.5", "Client Ledger", "fa fa-file-text-o", "clientledgero2c", true);
			menu.MenuItem("ELIT.4.3.6", "Monthly Trends", "fa fa-file-text-o", "monthlytrendso2c", true);
			menu.EndGroup();

			menu.EndGroup();

			#endregion

			#region Sales

			menu.BeginGroup("ELIT.9", "Sales System", "fa fa-sitemap");

			menu.BeginGroup("ELIT.9.1", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.9.1.1", "Market Hierarchies", "fa fa-pencil-square", "markethierarchies", true);
			menu.MenuItem("ELIT.9.1.2", "Sales Points", "fa fa-pencil-square", "salespoints", true);
			menu.MenuItem("ELIT.9.1.2A", "Allow to Set Central Warehouse", false);
			menu.MenuItem("ELIT.9.1.3", "Product Hierarchies", "fa fa-pencil-square", "producthierarchies", true);
			menu.MenuItem("ELIT.9.1.4", "Brands", "fa fa-pencil-square", "brands", true);
			menu.MenuItem("ELIT.9.1.5", "SKUs", "fa fa-pencil-square", "skus", true);
			menu.MenuItem("ELIT.9.1.6", "Channel Hierarchies", "fa fa-pencil-square", "channelhierarchies", true);
			menu.MenuItem("ELIT.9.1.7", "Customers", "fa fa-pencil-square", "customers", true);
			menu.MenuItem("ELIT.9.1.8", "Sales Officers", "fa fa-pencil-square", "salesofficers", true);
			menu.MenuItem("ELIT.9.1.9", "Product Prices", "fa fa-pencil-square", "skupricess", true);
			menu.MenuItem("ELIT.9.1.10", "Product VAT-SD-Comm", "fa fa-pencil-square", "skuvattaxes", true);
			menu.MenuItem("ELIT.9.1.11", "Customer Credit", "fa fa-pencil-square", "customercredit", true);
			menu.MenuItem("ELIT.9.1.12", "External Products", "fa fa-pencil-square", "extnlproducts", true);
			menu.MenuItem("ELIT.9.1.13", "Sales Promotions", "fa fa-pencil-square", "salespromotions", true);
			menu.MenuItem("ELIT.9.1.14", "Order Authorization Limit", "fa fa-pencil-square", "ordrauthlimit", true);
			menu.MenuItem("ELIT.9.1.30", "Edit Code (All Setups)", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.9.2", "Regular Activities", "fa fa-building");
			menu.MenuItem("ELIT.9.2.1", "Customer Opening Balance", "fa fa-puzzle-piece", "slscustsopnbal", true);
			menu.MenuItem("ELIT.9.2.1A", "Authorize Customer Opening Balance", false);
			menu.MenuItem("ELIT.9.2.2", "Customer Adjustment", "fa fa-pencil-square", "slscustsadjustment", true);
			menu.MenuItem("ELIT.9.2.2A", "Authorize Customer Adjustment", false);
			menu.MenuItem("ELIT.9.2.3", "Initial Stock", "fa fa-puzzle-piece", "slsinitstocks", true);
			menu.MenuItem("ELIT.9.2.3A", "Authorize Initial Stock", false);
			menu.MenuItem("ELIT.9.2.4", "Receive Stocks", "fa fa-reply-all", "slsrcvstocks", true);
			menu.MenuItem("ELIT.9.2.4A", "Authorize Receive Stocks", false);
			menu.MenuItem("ELIT.9.2.5", "Sales Orders", "fa fa-pencil-square", "slsorders", true);
			menu.MenuItem("ELIT.9.2.5A", "Authorize Sales Order", false);
			menu.MenuItem("ELIT.9.2.6", "Spot Sales", "fa fa-pencil-square", "slsdirectinvoices", true);
			menu.MenuItem("ELIT.9.2.6A", "Authorize Spot Sales", false);
			menu.MenuItem("ELIT.9.2.7", "Sales Invoices", "fa fa-pencil-square", "slsinvoices", true);
			menu.MenuItem("ELIT.9.2.7A", "Authorize Sales Invoice", false);
			menu.MenuItem("ELIT.9.2.8", "Payment Against Invoices", "fa fa-archive", "slsinvpayments", true);
			menu.MenuItem("ELIT.9.2.8A", "Authorize Payment Against Invoice", false);
			menu.MenuItem("ELIT.9.2.9", "Stock Transfers", "fa fa-archive", "slsstockxfers", true);
			menu.MenuItem("ELIT.9.2.9A", "Authorize Stock Transfer", false);
			menu.MenuItem("ELIT.9.2.10", "Receive Transferred Stocks", "fa fa-archive", "slsstockxferrcvs", true);
			menu.MenuItem("ELIT.9.2.10A", "Authorize Transferred Stock", false);
			menu.MenuItem("ELIT.9.2.11", "Fix Transfer Anomalies", "fa fa-archive", "slsstockxferanmls", true);
			menu.MenuItem("ELIT.9.2.11A", "Authorize Transfer Anomaly", false);
			menu.MenuItem("ELIT.9.2.12", "Sales Return", "fa fa-archive", "slsrtnstocks", true);
			menu.MenuItem("ELIT.9.2.12A", "Authorize Return Stock", false);
			menu.MenuItem("ELIT.9.2.13", "Damage Stocks", "fa fa-archive", "slsdmgstocks", true);
			menu.MenuItem("ELIT.9.2.13A", "Authorize Damage Stock", false);
			menu.MenuItem("ELIT.9.2.14", "Stock Take", "fa fa-archive", "slsstocktakes", true);
			menu.MenuItem("ELIT.9.2.14A", "Authorize Stock Take", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.9.3", "Reports", "fa fa-newspaper-o");
			menu.MenuItem("ELIT.9.3.1", "Customer Balance", "fa fa-th-list", "salescustbalance", true);
			menu.MenuItem("ELIT.9.3.2", "Customer Ledger", "fa fa-th-list", "salescustledger", true);
			menu.MenuItem("ELIT.9.3.3", "Current Stock", "fa fa-file-text-o", "salescurrentstock", true);
			menu.MenuItem("ELIT.9.3.4", "Stock Ledger", "fa fa-th-list", "salesstockledger", true);

			menu.EndGroup();

			menu.EndGroup();

			#endregion

			#region Purchase To Pay

			menu.BeginGroup("ELIT.5", "Purchase To Pay", "fa fa-shopping-cart");

			menu.BeginGroup("ELIT.5.1", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.5.1.1", "Product Types", "fa fa-address-card-o", "prodtypes", true);
			menu.MenuItem("ELIT.5.1.2", "Products", "fa fa-university", "products", true);
			menu.MenuItem("ELIT.5.1.3", "WO Terms & Conditions", "fa fa-pencil-square-o", "woterms", true);
			menu.MenuItem("ELIT.5.1.4", "VAT & AIT Rates", "fa fa-user-circle-o", "aitvatratep2p", true);
			menu.MenuItem("ELIT.5.1.10", "Edit Code (Basic Setup)", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.5.2", "Regular Activities", "fa fa-building");
			menu.MenuItem("ELIT.5.2.0", "Initial Stock", "fa fa-puzzle-piece", "initstocksp2p", true);
			menu.MenuItem("ELIT.5.2.0B", "Authorize Initial Stock", false);
			menu.MenuItem("ELIT.5.2.13", "Purchase Requisitions", "fa fa-puzzle-piece", "purchrequisitionsp2p", true);
			menu.MenuItem("ELIT.5.2.13A", "Authorize Purchase Requisition", false);
			menu.MenuItem("ELIT.5.2.1", "Issue Work Orders", "fa fa-smile-o", "workordersp2p", true);
			menu.MenuItem("ELIT.5.2.1A", "Work Order Attachment", false);
			menu.MenuItem("ELIT.5.2.1B", "Authorize Work Order", false);
			menu.MenuItem("ELIT.5.2.1C", "Freeze Work Order", false);
			menu.MenuItem("ELIT.5.2.12", "Advance Payments", "fa fa-money", "advpaymntsp2p", true);
			menu.MenuItem("ELIT.5.2.12A", "Authorize Advance Payment", false);
			menu.MenuItem("ELIT.5.2.2", "Receive Items at CS", "fa fa-reply-all", "stksrcvdatcsp2p", true);
			menu.MenuItem("ELIT.5.2.2A", "Authorize Receive Items at CS", false);
			menu.MenuItem("ELIT.5.2.3", "Receive Invoices", "fa fa-money", "invoicesp2p", true);
			menu.MenuItem("ELIT.5.2.3A", "Invoice Attachment", false);
			menu.MenuItem("ELIT.5.2.3B", "Authorize Invoice", false);
			menu.MenuItem("ELIT.5.2.4", "Cash Purchase", "fa fa-archive", "cashpurchases", true);
			menu.MenuItem("ELIT.5.2.4A", "Invoice Attachment", false);
			menu.MenuItem("ELIT.5.2.4B", "Authorize Cash Purchase", false);
			menu.MenuItem("ELIT.5.2.5", "Payment Against Invoice", "fa fa-archive", "paymentsp2p", true);
			menu.MenuItem("ELIT.5.2.5A", "Authorize Payment Against Invoice", false);
			menu.MenuItem("ELIT.5.2.6", "Goods Transfer", "fa fa-archive", "gdstransfers", true);
			menu.MenuItem("ELIT.5.2.6A", "Authorize Goods Transfer", false);
			menu.MenuItem("ELIT.5.2.7", "Receive Goods Transfer", "fa fa-archive", "gdsreceives", true);
			menu.MenuItem("ELIT.5.2.7A", "Authorize Receive Goods Transfer", false);
			menu.MenuItem("ELIT.5.2.8", "Fix Transfer Anomalies", "fa fa-archive", "transferanomalies", true);
			menu.MenuItem("ELIT.5.2.8A", "Authorize Transfer Anomalies", false);
			menu.MenuItem("ELIT.5.2.9", "Consumption of Goods", "fa fa-archive", "gdscnsmpnsp2p", true);
			menu.MenuItem("ELIT.5.2.9A", "Authorize Consumption of Goods", false);
			menu.MenuItem("ELIT.5.2.10", "Damage of Goods", "fa fa-archive", "gdsdamagesp2p", true);
			menu.MenuItem("ELIT.5.2.10A", "Authorize Damage of Goods", false);
			menu.MenuItem("ELIT.5.2.11", "Stock Take of Goods", "fa fa-archive", "stocktakes", true);
			menu.MenuItem("ELIT.5.2.11A", "Authorize Stock Take of Goods", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.5.3", "Reports", "fa fa-newspaper-o");
			menu.MenuItem("ELIT.5.3.1", "GL Vouchers", "fa fa-th-list", "glvouchersp2p", true);
			menu.MenuItem("ELIT.5.3.2", "Current Stock", "fa fa-file-text-o", "currentstockp2p", true);
			menu.MenuItem("ELIT.5.3.3", "Stock Ledger", "fa fa-file-text-o", "stockledgerp2p", true);
			menu.MenuItem("ELIT.5.3.4", "Supplier Ledger", "fa fa-file-text-o", "supplierledgerp2p", true);
			menu.EndGroup();

			menu.EndGroup();

			#endregion

			#region Fixed Assets

			menu.BeginGroup("ELIT.6", "Fixed Assets", "fa fa-sitemap");

			menu.BeginGroup("ELIT.6.1", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.6.1.1", "Asset Types", "fa fa-address-card-o", "assettypes", true);
			menu.MenuItem("ELIT.6.1.2", "Asset Categories", "fa fa-university", "assetcategories", true);
			menu.MenuItem("ELIT.6.1.3", "Asset Items", "fa fa-credit-card", "assetitems", true);
			menu.MenuItem("ELIT.6.1.6", "Asset Hierarchies", "fa fa-credit-card", "assethierarchies", true);
			menu.MenuItem("ELIT.6.1.4", "Locations", "fa fa-pencil-square", "locations", true);
			menu.MenuItem("ELIT.6.1.5", "VAT & AIT Rates", "fa fa-user-circle-o", "aitvatratefa", true);
			menu.MenuItem("ELIT.6.1.10", "Edit Code (Basic Setup)", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.6.2", "Regular Activities", "fa fa-building");
			menu.MenuItem("ELIT.6.2.0", "Initial Fixed Assets", "fa fa-puzzle-piece", "initstocksfa", true);
			menu.MenuItem("ELIT.6.2.0B", "Authorize Initial Fixed Assets", false);
			menu.MenuItem("ELIT.6.2.15", "Purchase Requisitions", "fa fa-puzzle-piece", "purchrequisitionsfa", true);
			menu.MenuItem("ELIT.6.2.15A", "Authorize Purchase Requisition", false);
			menu.MenuItem("ELIT.6.2.1", "Issue Work Orders", "fa fa-smile-o", "workordersfa", true);
			menu.MenuItem("ELIT.6.2.1A", "Work Order Attachment", false);
			menu.MenuItem("ELIT.6.2.1B", "Authorize Work Order", false);
			menu.MenuItem("ELIT.6.2.1C", "Freeze Work Order", false);
			menu.MenuItem("ELIT.6.2.14", "Advance Payments", "fa fa-money", "advpaymntsfa", true);
			menu.MenuItem("ELIT.6.2.14A", "Authorize Advance Payment", false);
			menu.MenuItem("ELIT.6.2.2", "Received Items At CS", "fa fa-reply-all", "stksrcvdatcsfa", true);
			menu.MenuItem("ELIT.6.2.2A", "Authorize Receive Items at CS", false);
			menu.MenuItem("ELIT.6.2.3", "Receive Invoices", "fa fa-money", "invoicesfa", true);
			menu.MenuItem("ELIT.6.2.3A", "Invoice Attachment", false);
			menu.MenuItem("ELIT.6.2.3B", "Authorize Invoice", false);
			menu.MenuItem("ELIT.6.2.4", "Payment Against Invoice", "fa fa-archive", "paymentsfa", true);
			menu.MenuItem("ELIT.6.2.4A", "Authorize Payment Against Invoice", false);
			menu.MenuItem("ELIT.6.2.5", "Item Acquisition", "fa fa-smile-o", "itemsacquisition", true);
			menu.MenuItem("ELIT.6.2.5A", "Update Item Data", "fa fa-smile-o", "updfaitmdescription", true);
			menu.MenuItem("ELIT.6.2.6", "Item Installation", "fa fa-share-square", "astinstalns", true);
			menu.MenuItem("ELIT.6.2.6A", "Authorize Item Installation", false);
			menu.MenuItem("ELIT.6.2.7", "Transfer Fixed Asset", "fa fa-money", "assetxfers", true);
			menu.MenuItem("ELIT.6.2.7A", "Authorize Transfer Fixed Asset", false);
			menu.MenuItem("ELIT.6.2.8", "Write Off", "fa fa-archive", "astwriteoffs", true);
			menu.MenuItem("ELIT.6.2.8A", "Authorize Write Off", false);
			menu.MenuItem("ELIT.6.2.9", "Asset Sales", "fa fa-archive", "astsales", true);
			menu.MenuItem("ELIT.6.2.9A", "Authorize Asset Sales", false);
			menu.MenuItem("ELIT.6.2.10", "Add Asset Value", "fa fa-archive", "astaddvalues", true);
			menu.MenuItem("ELIT.6.2.10A", "Authorize Add Asset Value", false);
			menu.MenuItem("ELIT.6.2.11", "Reduce Asset Value", "fa fa-archive", "assetreducesvalue", true);
			menu.MenuItem("ELIT.6.2.11A", "Authorize Reduce Asset Value", false);
			menu.MenuItem("ELIT.6.2.12", "No Depreciation Mark", "fa fa-user-circle-o", "nodeprnmark", true);
			menu.MenuItem("ELIT.6.2.13", "Depreciation Calculation", "fa fa-user-circle-o", "calcdepreciation", true);
			menu.EndGroup();

			menu.BeginGroup("ELIT.6.3", "Reports", "fa fa-newspaper-o");
			menu.MenuItem("ELIT.6.3.1", "GL Vouchers", "fa fa-th-list", "glvouchersfa", true);
			menu.MenuItem("ELIT.6.3.2", "Current Stock", "fa fa-file-text-o", "currentstockfa", true);
			menu.MenuItem("ELIT.6.3.3", "Stock Ledger", "fa fa-file-text-o", "stockledgerfa", true);
			menu.MenuItem("ELIT.6.3.4", "Item Details", "fa fa-file-text-o", "faitemdetail", true);
			menu.MenuItem("ELIT.6.3.5", "Fixed Asset List", "fa fa-file-text-o", "faitemsatglance", true);
			menu.MenuItem("ELIT.6.3.6", "Waiting Acquisition", "fa fa-file-text-o", "faitemswtngaqstn", true);
			menu.MenuItem("ELIT.6.3.7", "Acquired Assets", "fa fa-file-text-o", "faitemsacquire", true);
			menu.MenuItem("ELIT.6.3.8", "Waiting Installation", "fa fa-file-text-o", "faitemswtnginstall", true);
			menu.MenuItem("ELIT.6.3.9", "No Depreciation Marked", "fa fa-file-text-o", "faitemsnodprn", true);
			menu.MenuItem("ELIT.6.3.10", "Depreciation Report", "fa fa-file-text-o", "faitemsdprnrpt", true);
			menu.MenuItem("ELIT.6.3.11", "Supplier Ledger", "fa fa-file-text-o", "fasupplierledger", true);
			menu.EndGroup();

			menu.EndGroup();

			#endregion

			#region Project Management

			menu.BeginGroup("ELIT.7", "Task Management", "fa fa-users");

			menu.BeginGroup("ELIT.7.1", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.7.1.1", "Developers", "fa fa-user-circle-o", "developers", true);
			menu.MenuItem("ELIT.7.1.2", "Support Teams", "fa fa-user-circle-o", "supportteams", true);
			menu.MenuItem("ELIT.7.1.2A", "QA Teams", "fa fa-user-circle-o", "qateams", true);
			menu.MenuItem("ELIT.7.1.3", "Priorities", "fa fa-check-square-o", "priorities", true);
			menu.MenuItem("ELIT.7.1.4", "Task Statuses", "fa fa-pencil-square", "taskstatuses", true);
			menu.MenuItem("ELIT.7.1.5", "Task Categories", "fa fa-check-square-o", "taskcategories", true);
			menu.MenuItem("ELIT.7.1.6", "Task Types", "fa fa-check-square-o", "tasktypes", true);
			menu.MenuItem("ELIT.7.1.7", "Team Spaces", "fa fa-user-circle-o", "teamspaces", true);
			menu.MenuItem("ELIT.7.1.8", "Team Spaces Attributes", false);
			menu.MenuItem("ELIT.7.1.9", "User Projects", "fa fa-product-hunt", "tsuserprojects", true);
			menu.MenuItem("ELIT.7.1.10", "Edit Code (All Setups)", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.7.2", "Regular Activities", "fa fa-building");
			menu.MenuItem("ELIT.7.2.1", "Tasks", "fa fa-smile-o", "tasks", true);
			menu.MenuItem("ELIT.7.2.1A", "Complete Task", false);
			menu.MenuItem("ELIT.7.2.2", "My Tasks", "fa fa-tasks", "mytasks", true);
			menu.MenuItem("ELIT.7.2.2A", "Allow Edit Task Time", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.7.3", "Reports", "fa fa-newspaper-o");
			menu.MenuItem("ELIT.7.3.1", "Task Reports", "fa fa-file-text-o", "taskreport", true);
			menu.EndGroup();

			menu.EndGroup();

			#endregion

			#region Attendance System

			menu.BeginGroup("ELIT.8", "Attendance System", "fa fa-calendar");

			menu.BeginGroup("ELIT.8.1", "Basic Setup", "fa fa-wrench");
			menu.MenuItem("ELIT.8.1.1", "Ip/Mac Entries", "fa fa-user-circle-o", "ipmacentries", true);
			menu.MenuItem("ELIT.8.1.1A", "Authorize Ip/Mac", false);
			menu.MenuItem("ELIT.8.1.2", "Holiday Calendar", "fa fa-calendar", "calendar", true);
			menu.MenuItem("ELIT.8.1.3", "Ramadan Calendar", "fa fa-calendar", "ramadan", true);
			menu.MenuItem("ELIT.8.1.15", "Special Edit/Delete", false);
			menu.EndGroup();

			menu.BeginGroup("ELIT.8.2", "Regular Activities", "fa fa-building");
			menu.MenuItem("ELIT.8.2.1", "Employee Leaves", "fa fa-smile-o", "empleaves", true);
			menu.MenuItem("ELIT.8.2.1A", "Authorize Leave", false);
			menu.MenuItem("ELIT.8.2.2", "Late Entries", "fa fa-tasks", "emplates", true);
			menu.MenuItem("ELIT.8.2.3", "Client Visits", "fa fa-tasks", "empclntvsts", true);
			menu.MenuItem("ELIT.8.2.4", "Home Offices", "fa fa-tasks", "emphmofcs", true);
			menu.MenuItem("ELIT.8.2.4A", "Authorize Home Office", false);
			menu.MenuItem("ELIT.8.2.5", "View All Employees Absent", false);
			menu.MenuItem("ELIT.8.2.6", "Asset Bookings", "fa fa-tasks", "assetbookings", true);
			menu.EndGroup();

			menu.BeginGroup("ELIT.8.3", "Reports", "fa fa-newspaper-o");
			menu.MenuItem("ELIT.8.3.1", "Login History", "fa fa-tasks", "loginhistory", true);
			menu.MenuItem("ELIT.8.3.2", "Attendance Reports", "fa fa-file-text-o", "atnreports", true);
			menu.EndGroup();

			menu.EndGroup();

			#endregion

			return menu;
		}

		#endregion

		#region Miscellaneous functions

		/// <summary>
		/// 
		/// </summary>
		/// <param name="text"></param>
		/// <param name="width"></param>
		/// <returns></returns>
		[SupportedOSPlatform("windows")]
		private static float GetHeight(string text, float width)
		{
			Font subFont = new(familyName: "Arial", emSize: 8f, style: FontStyle.Regular);
			StringFormat sf = new();
			int sysWidth = Convert.ToInt32(width * 100f);
			Graphics g = Graphics.FromHwnd(IntPtr.Zero);
			SizeF newSz = g.MeasureString(text, subFont, sysWidth, sf);

			return (newSz.Height / 100f);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="reportType"></param>
		/// <param name="rdlc"></param>
		/// <param name="compare"></param>
		/// <returns></returns>
		internal static string GetReportFileName(short reportType, bool rdlc, bool compare)
		{
			string fileName;
			if (rdlc)
			{
				fileName = reportType switch
				{
					3 => "rptCashflow{0}.rdlc",
					2 => "rptBalanceSheet{0}.rdlc",
					_ => "rptProfitLoss{0}.rdlc",
				};

				fileName = string.Format(fileName, compare ? "Compare" : "");
			}
			else
			{
				fileName = reportType switch
				{
					3 => "Cashflow",
					2 => "BalanceSheet",
					_ => "ProfitLoss",
				};
			}

			return fileName;
		}

		/// <summary>
		/// Determines the number of rows to exclude from a given <see cref="DataTable"/> based on the calculated height
		/// of values in specified fields.
		/// </summary>
		/// <remarks>This method calculates the height of values in the specified fields for each row in
		/// the <paramref name="table"/>. If the calculated height exceeds 0.18, the excess height is accumulated. The
		/// final result is determined by dividing the accumulated height by 0.18.</remarks>
		/// <param name="table">The <see cref="DataTable"/> containing the rows to evaluate.</param>
		/// <param name="field1">The name of the first field used to calculate height. Can be <see langword="null"/> or empty.</param>
		/// <param name="width1">The width parameter used to calculate the height for <paramref name="field1"/>.</param>
		/// <param name="field2">The name of the second field used to calculate height. Can be <see langword="null"/> or empty.</param>
		/// <param name="width2">The width parameter used to calculate the height for <paramref name="field2"/>.</param>
		/// <returns>The number of rows to exclude, calculated as the total adjusted height divided by 0.18. Returns 0 if no rows
		/// meet the criteria.</returns>
		[SupportedOSPlatform("windows")]
		public static int GetRowToExclude(DataTable table, string field1, float width1, string field2, float width2)
		{
			float height = 0;
			if (!string.IsNullOrEmpty(field1) || !string.IsNullOrEmpty(field2))
			{
				foreach (DataRow row in table.Rows)
				{
					float height1 = 0;
					if (!string.IsNullOrEmpty(field1))
					{
						string value = Convert.ToString(row[field1]);
						height1 = GetHeight(value, width1);
					}

					float height2 = 0;
					if (!string.IsNullOrEmpty(field2))
					{
						string value = Convert.ToString(row[field2]);
						height2 = GetHeight(value, width2);
					}

					height1 = Math.Max(height2, height1);
					if (height1 > 0.18f)
						height += (height1 - 0.18f);
				}
			}
			return Convert.ToInt32(height / 0.18);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="minutes"></param>
		/// <returns></returns>
		public static string ConvertToHourMinutes(int minutes)
		{
			string s = string.Empty;
			if (minutes >= 60)
			{
				int rem = minutes % 60;
				s = $"{(minutes - rem) / 60}h";

				minutes = rem;
			}

			if (minutes > 0)
			{
				if (s.Length > 0)
					s += " ";
				s += $"{minutes}m";
			}

			return s;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="base64String"></param>
		/// <returns></returns>
		public static string ConvertFromBase64String(string base64String)
		{
			ArgumentNullException.ThrowIfNull(base64String);
			if (string.IsNullOrEmpty(base64String))
				return string.Empty;

			byte[] data = Convert.FromBase64String(base64String);
			return System.Text.Encoding.UTF8.GetString(data);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="logger"></param>
		/// <param name="message"></param>
		public static void LogError(this ILogger logger, string message)
		{
			logger.LogError(message: message, args: null);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="s"></param>
		/// <param name="length"></param>
		/// <returns></returns>
		public static string MakeCleanString(this string s, int length, bool removeComma = false)
		{
			string sd = $"{s}";
			sd = sd.Replace(oldValue: Environment.NewLine, newValue: " ");
			sd = sd.Replace(oldValue: "\n", newValue: " ");
			sd = sd.Replace(oldValue: "\r", newValue: " ");
			sd = Regex.Replace(sd, @"\s+", " ");
			sd = Ease.NetCore.Utility.Global.StringFunctions.Left(inputString: sd, length: length);
			if (removeComma)
				sd = sd.Replace(oldChar: ',', newChar: ' ');

			return sd;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="row"></param>
		/// <param name="delimiter"></param>
		/// <returns></returns>
		public static string LineData(this DataRow row, string delimiter)
		{
			return string.Join(delimiter, row.ItemArray);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="enumValue"></param>
		/// <returns></returns>
		public static string GetDescription<T>(this T enumValue) where T : struct, IConvertible
		{
			if (!typeof(T).IsEnum)
				return null;

			string description = enumValue.ToString();
			System.Reflection.FieldInfo fieldInfo = enumValue.GetType().GetField(enumValue.ToString());

			if (fieldInfo != null)
			{
				object[] attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), true);
				if (attributes != null && attributes.Length > 0)
					description = ((DescriptionAttribute)attributes[0]).Description;
			}

			return description;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="enumValue"></param>
		/// <returns></returns>
		public static string GetLastDescription<T>(this T enumValue) where T : struct, IConvertible
		{
			string[] values = enumValue.ToString().Split(separator: [","], options: StringSplitOptions.TrimEntries);
			if (values?.Length <= 0)
				return string.Empty;

			object lastNumericValue = Enum.Parse(enumType: enumValue.GetType(), value: values[^1]);
			T value = (T)Convert.ChangeType(lastNumericValue, typeof(T));

			return GetDescription(value);
		}

		#endregion
	}
}
