using System;
using System.Data;
using System.Data.Common;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using digioz;
using System.Collections.Generic;

namespace digioz
{
    /// <summary>
    /// Exposes service methods for WebLinks Manager
    /// </summary>
    public class WebLinkManagement
    {
        private static PortalSettings coPortalSettings;
        private static Regex coUrlValidation = new Regex(@"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?");

        /// <summary>
        /// Adds a Weblink to the datastore and returns true if successful. Makes the added link active as soon as added.
        /// </summary>
        /// <param name="psName">Name of the link</param>
        /// <param name="psUrl">URL of the link</param>
        /// <param name="psDetail">Detail of the link</param>
        /// <param name="psCategory">Link Category</param>
        /// <returns>bool</returns>
        public static bool AddWebLink(string psName, string psUrl, string psDetail, string psCategory)
        {
            return AddWebLinkImplement(psName, psUrl, psDetail, psCategory, 1);
        }

        /// <summary>
        /// Requests to add a Weblink and returns true if successful. Makes the added link pending for approval after adding.
        /// </summary>
        /// <param name="psName">Name of the link</param>
        /// <param name="psUrl">URL of the link</param>
        /// <param name="psDetail">Detail of the link</param>
        /// <param name="psCategory">Link Category</param>
        /// <returns>bool</returns>
        public static bool AddWebLinkRequest(string psName, string psUrl, string psDetail, string psCategory)
        {
            return AddWebLinkImplement(psName, psUrl, psDetail, psCategory, 0);
        }

        /// <summary>
        /// Adds a Weblink to the datastore and returns true if successful. Makes the added link active as soon as added.
        /// </summary>
        /// <param name="psName">Name of the link</param>
        /// <param name="psUrl">URL of the link</param>
        /// <param name="psDetail">Detail of the link</param>
        /// <param name="psCategory">Link Category</param>
        /// <param name="psStatus">Status of the link. Pass 0 or 1 for pending or active respectively</param>
        /// <returns>bool</returns>
        private static bool AddWebLinkImplement(string psName, string psUrl, string psDetail, string psCategory, short psStatus)
        {
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();

            if (coPortalSettings.DBRelational == true)
            {
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);
                try
                {
                    //validating inputs
                    if (psName.Length > 100)
                        throw new ArgumentException("Name can't be longer than 100 characters", "psName");
                    if (psName.Length < 1)
                        throw new ArgumentException("Name can't be empty", "psName");
                    if (!coUrlValidation.Match(psUrl).Success)
                        throw new ArgumentException("The Url is not valid", "psUrl");

                    //on successful validation 
                    short lsStatus = psStatus;
                    DateTime ldAdded = DateTime.Now; //current datetime is added datetime value.

                    DbParameter[] loPars = new DbParameter[6]; //preparing sql parameters.
                    loPars[0] = new SqlParameter("@link_name", DbType.String);
                    loPars[0].Value = psName;
                    loPars[1] = new SqlParameter("@link_url", DbType.String);
                    loPars[1].Value = psUrl;
                    loPars[2] = new SqlParameter("@link_detail", DbType.String);
                    loPars[2].Value = psDetail;
                    loPars[3] = new SqlParameter("@link_category", DbType.String);
                    loPars[3].Value = psCategory;
                    loPars[4] = new SqlParameter("@link_status", DbType.Int16);
                    loPars[4].Value = lsStatus;
                    loPars[5] = new SqlParameter("@link_added", DbType.DateTime);
                    loPars[5].Value = ldAdded;
                    int liCount = 0;
                    loDb.openConnection();
                    loDb.ExecDBProc("spInsertLink", out liCount, loPars); //executing the query
                    loDb.closeConnection();
                    if (liCount > 0) //making sure query execution was successful.
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Get a weblink by it's Link Id
        /// </summary>
        /// <param name="piId">A valid id for the link to retrieve</param>
        /// <returns>WebLink</returns>
        public static WebLink GetWebLink(int piId)
        {
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();

            if (coPortalSettings.DBRelational == true)
            {
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);
                DataTable loDT;
                DbParameter[] loPars = new DbParameter[1];
                loPars[0] = new SqlParameter("@id", SqlDbType.Int);
                loPars[0].Value = piId;
                loDb.openConnection();
                loDT = loDb.QueryDBDataset("SELECT * FROM tblLinks WHERE link_id = @id", loPars);
                loDb.closeConnection();

                if (loDT.Rows.Count > 0)
                {
                    DataRow loDr = loDT.Rows[0];
                    int liId = Convert.ToInt32(loDr["link_id"]);
                    string lsName = loDr["link_name"].ToString();
                    string lsUrl = loDr["link_url"].ToString();
                    string lsDetail = loDr["link_detail"].ToString();
                    string lsCategory = loDr["link_category"].ToString();
                    string lsUpdated = loDr["link_updated"].ToString();
                    string lsAdded = loDr["link_added"].ToString();
                    short lsStatus = Convert.ToInt16(loDr["link_status"]);
                    return new WebLink(liId, lsName, lsUrl, lsDetail, lsCategory, lsUpdated, lsAdded, lsStatus);
                    //return new WebLink(Convert.ToInt32(loDr["link_id"]), loDr["link_name"].ToString(), loDr["link_url"].ToString(), loDr["link_detail"].ToString(), loDr["link_category"].ToString(), loDr["link_updated"].ToString(), loDr["link_added"].ToString(), Convert.ToInt32(loDr["link_status"]));
                }
                else
                {
                    throw new ArgumentException("Invalid Id provided.", "piId");
                }
            }
            else
            {
                return new WebLink();
            }
        }

        /// <summary>
        /// Returns a list of Pending WebLinks
        /// </summary>
        /// <returns></returns>
        public static List<WebLink> GetAllPendingWebLinks()
        {
            return GetAllWebLinks(0);
        }

        /// <summary>
        /// Retrieves a list of Active WebLinks
        /// </summary>
        /// <returns></returns>        
        public static List<WebLink> GetAllActiveWebLinks()
        {
            return GetAllWebLinks(1);
        }

        /// <summary>
        /// Returns a list of Deleted Weblinks
        /// </summary>
        /// <returns></returns>
        public static List<WebLink> GetAllDeletedWebLinks()
        {
            return GetAllWebLinks(2);
        }

        /// <summary>
        /// Retrieves a list of links based on the parameter specified.
        /// </summary>
        /// <param name="psStatus">Status of the links to retrieve. Pass 0, 1 or 2 for pending, active and deleted links respectively.</param>
        /// <returns></returns>
        public static List<WebLink> GetAllWebLinks(short psStatus)
        {
            List<WebLink> loResult = new List<WebLink>();
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();

            if (coPortalSettings.DBRelational == true)
            {
                DataTable loDT;
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);
                loDb.openConnection();
                loDT = loDb.QueryDBDataset("SELECT * FROM tblLinks WHERE link_status = " + psStatus.ToString() + ";");
                loDb.closeConnection();

                foreach (DataRow loDr in loDT.Rows)
                {
                    int liId = Convert.ToInt32(loDr["link_id"]);
                    string lsName = loDr["link_name"].ToString();
                    string lsUrl = loDr["link_url"].ToString();
                    string lsDetail = loDr["link_detail"].ToString();
                    string lsCategory = loDr["link_category"].ToString();
                    string lsUpdated = loDr["link_updated"].ToString();
                    string lsAdded = loDr["link_added"].ToString();
                    short lsStatus = Convert.ToInt16(loDr["link_status"]);
                    WebLink loWebLink = new WebLink(liId, lsName, lsUrl, lsDetail, lsCategory, lsUpdated, lsAdded, lsStatus);
                    loResult.Add(loWebLink);
                }
            }

            return loResult;
        }

        /// <summary>
        /// Updates an existing WebLink specified in the piId.
        /// </summary>
        /// <param name="piId">Id of the Link to update</param>
        /// <param name="psName">New Name for the link</param>
        /// <param name="psUrl">New Url for the link</param>
        /// <param name="psDetail">New Detail for the link</param>
        /// <param name="psCategory">New Category for the link</param>
        /// <returns></returns>
        public static bool UpdateWebLink(int piId, string psName, string psUrl, string psDetail, string psCategory)
        {
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();

            try
            {
                //validating inputs
                if (psName.Length > 100)
                {
                    throw new ArgumentException("Name can't be longer than 100 characters", "psName");
                }
                if (psName.Length < 1)
                {
                    throw new ArgumentException("Name can't be empty", "psName");
                }
                if (!coUrlValidation.Match(psUrl).Success)
                {
                    throw new ArgumentException("The Url is not valid", "psUrl");
                }
            }
            catch
            {
                return false;
            }

            if (coPortalSettings.DBRelational == true)
            {
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);

                try
                {
                    DateTime ldUpdated = DateTime.Now; //current datetime is the updated datetime
                    DbParameter[] loPars = new DbParameter[6]; //preparing sql parameters.
                    loPars[0] = new SqlParameter("@link_id", DbType.Int32);
                    loPars[0].Value = piId;
                    loPars[1] = new SqlParameter("@link_name", DbType.String);
                    loPars[1].Value = psName;
                    loPars[2] = new SqlParameter("@link_url", DbType.String);
                    loPars[2].Value = psUrl;
                    loPars[3] = new SqlParameter("@link_category", DbType.String);
                    loPars[3].Value = psCategory;
                    loPars[4] = new SqlParameter("@link_detail", DbType.String);
                    loPars[4].Value = psDetail;
                    loPars[5] = new SqlParameter("@link_updated", DbType.DateTime);
                    loPars[5].Value = ldUpdated;
                    int liCount = 0;
                    loDb.openConnection();
                    loDb.ExecDBProc("spUpdateLink", out liCount, loPars); //executing the query
                    loDb.closeConnection();
                    if (liCount > 0) //making sure query execution was successful.
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Deletes a WebLink by marking the Link as deleted in the database.
        /// </summary>
        /// <param name="piId">Id of the link to delete. Nothing happens if invalid id is specified</param>
        /// <returns></returns>
        public static bool DeleteWebLink(int piId)
        {
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();

            if (coPortalSettings.DBRelational == true)
            {
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);

                try
                {
                    DateTime ldUpdated = DateTime.Now; //current datetime is the updated datetime
                    DbParameter[] loPars = new DbParameter[2]; //preparing sql parameters.
                    loPars[0] = new SqlParameter("@link_id", DbType.Int32);
                    loPars[0].Value = piId;
                    loPars[1] = new SqlParameter("@link_updated", DbType.DateTime);
                    loPars[1].Value = ldUpdated;
                    int liCount = 0;
                    loDb.openConnection();
                    loDb.ExecDBProc("spDeleteLink", out liCount, loPars); //executing the query
                    loDb.closeConnection();
                    if (liCount > 0) //making sure query execution was successful.
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch
                { return false; }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Restores a Deleted Link.
        /// </summary>
        /// <param name="piId">Id of the deleted link to restore. If the Id specified is not deleted Id then nothing happens</param>
        /// <returns></returns>
        public static bool RestoreWebLink(int piId)
        {
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();

            if (coPortalSettings.DBRelational == true)
            {
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);

                try
                {
                    DateTime ldUpdated = DateTime.Now; //current datetime is the updated datetime
                    DbParameter[] loPars = new DbParameter[2]; //preparing sql parameters.
                    loPars[0] = new SqlParameter("@link_id", DbType.Int32);
                    loPars[0].Value = piId;
                    loPars[1] = new SqlParameter("@link_updated", DbType.DateTime);
                    loPars[1].Value = ldUpdated;
                    int liCount = 0;
                    loDb.openConnection();
                    loDb.ExecDBProc("spRestoreLink", out liCount, loPars); //executing the query
                    loDb.closeConnection();
                    if (liCount > 0) //making sure query execution was successful.
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Approve a pending link
        /// </summary>
        /// <param name="piId">Id of the pending Weblink. Nothing happens if invalid id is specified</param>
        /// <returns></returns>
        public static bool ApproveWebLink(int piId)
        {
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();

            if (coPortalSettings.DBRelational == true)
            {
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);

                try
                {
                    DateTime ldUpdated = DateTime.Now; //current datetime is the updated datetime
                    DbParameter[] loPars = new DbParameter[2]; //preparing sql parameters.
                    loPars[0] = new SqlParameter("@link_id", DbType.Int32);
                    loPars[0].Value = piId;
                    loPars[1] = new SqlParameter("@link_updated", DbType.DateTime);
                    loPars[1].Value = ldUpdated;
                    int liCount = 0;
                    loDb.openConnection();
                    loDb.ExecDBProc("spApproveLink", out liCount, loPars); //executing the query
                    loDb.closeConnection();
                    if (liCount > 0) //making sure query execution was successful.
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Retrieves a list of all categories from Active Weblinks
        /// </summary>
        /// <returns>List string</returns>
        public static List<string> GetAllCategories()
        {
            coPortalSettings = PortalSettingsManagement.GetPortalSettings();
            List<string> loAllCategories = new List<string>();

            if (coPortalSettings.DBRelational == true)
            {
                IDataRelational loDb = DataFactory.GetDataObject(coPortalSettings);
                DataTable loDT;

                string lsQuery = "SELECT DISTINCT link_category FROM tblLinks WHERE link_status=1;";
                loDb.openConnection();
                loDT = loDb.QueryDBDataset(lsQuery);
                loDb.closeConnection();

                foreach (DataRow loDr in loDT.Rows)
                {
                    loAllCategories.Add(loDr[0].ToString());
                }
            }

            return loAllCategories;
        }
    }
}