using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Xml;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;
using TABS.MailCarrier.WebSDK;
using TABS.MailCarrier.StgBase;
using TABS.MailCarrier.WebSDK.Mail;
using TABS.MailCarrier.WebSDK.Contact;

public partial class Mail_GetRecipients : System.Web.UI.Page
{
    static object _thisLock4DomainUsers = new object();
    static object _thisLock4SharedAddrBook = new object();
    static object _thisLock4Organization = new object();
    static object _thisLock4ExtMailAddr = new object();

    protected void Page_Load(object sender, EventArgs e)
    {
    }

    [WebMethod]
    public static List<string> GetAutoCmplRecipientList4Actb()
    {
        return GetAutoCmplRecipientListData4Actb();
    }

    public static List<string> GetAutoCmplRecipientListData4Actb()
    {
        RecipientCollection rcptList = new RecipientCollection();
        LoadAutoCmplData(rcptList);

        List<string> displayList = new List<string>();
        foreach (Recipient rcpt in rcptList)
        {
            string mailAddr = rcpt.Address.Trim();
            string displayName = rcpt.Name.Trim();
            if (displayName != "")
            {
                displayName = displayName.Replace("\"", " ");
                displayList.Add(string.Format("\"{0}\" ({1})", displayName, mailAddr));
            }
            else
            {
                displayList.Add(mailAddr);
            }
        }
        return displayList;
    }

    private static void LoadAutoCmplData(RecipientCollection rcptList)
    {
        bool allowDuplicate = false;
        bool allowSort = false;
        foreach (AppSetting.RcptAutoCompleteSourceType srcType in AppSetting.RcptAutoCompleteSources)
        {
            switch (srcType)
            {
                case AppSetting.RcptAutoCompleteSourceType.RecentUsed:
                    LoadRecentUsed(rcptList);
                    break;
                case AppSetting.RcptAutoCompleteSourceType.DomainUsers:
                    LoadDomainUsers(rcptList);
                    break;
                case AppSetting.RcptAutoCompleteSourceType.UserContacts:
                    LoadUserContacts(rcptList);
                    break;
                case AppSetting.RcptAutoCompleteSourceType.SharedContacts:
                    LoadSharedContacts(rcptList);
                    break;
                case AppSetting.RcptAutoCompleteSourceType.Organization:
                    LoadOrganization(rcptList);
                    break;
                case AppSetting.RcptAutoCompleteSourceType.ExternalMailAddrs:
                    LoadExternalMailAddressFromOrgz(rcptList);
                    break;
                case AppSetting.RcptAutoCompleteSourceType.AllowDuplicate:
                    allowDuplicate = true;
                    break;
                case AppSetting.RcptAutoCompleteSourceType.AllowSort:
                    allowSort = true;
                    break;
            }
        }

        if (allowDuplicate)
            rcptList.RemoveDuplicateByNameAddress();
        else
            rcptList.RemoveDuplicate();
        ExceptAddress(rcptList);
        if (allowSort) rcptList.Sort();
    }

    private static void LoadRecentUsed(RecipientCollection rcptList)
    {
        UserMailbox userMailbox = new UserMailbox(WebUser.CurrentUser.DomainUserID);
        Recipient[] recipients = userMailbox.GetRecentUsedRecipients(30);
        rcptList.AddRange(recipients);
    }

    private static void LoadDomainUsers(RecipientCollection rcptList)
    {
        if (AppSetting.RcptAutoCompleteCacheTimeMin == 0)
        {
            rcptList.AddRange(LoadDomainUsersFromDB());
        }
        else
        {
            HttpContext httpContext = HttpContext.Current;
            // 도메인 사용자/메일링리스트는 캐시한다.
            string cacheKey = "AutoCmplDomainUsers:" + WebUser.CurrentUser.DomainID.ToString();
            RecipientCollection list = (RecipientCollection)httpContext.Cache[cacheKey];
            if (list == null)
            {
                lock (_thisLock4DomainUsers)
                {
                    list = (RecipientCollection)httpContext.Cache[cacheKey];
                    if (list == null)
                    {
                        list = LoadDomainUsersFromDB();
                        httpContext.Cache.Insert(cacheKey, list, null, DateTime.UtcNow.AddMinutes(AppSetting.RcptAutoCompleteCacheTimeMin), System.Web.Caching.Cache.NoSlidingExpiration);
                    }
                }
            }
            rcptList.AddRange(list);
        }
    }

    private static RecipientCollection LoadDomainUsersFromDB()
    {
        RecipientCollection list = new RecipientCollection();
        SqlConnection conn = new SqlConnection(GlobalConfig.ConnString);
        string domain = WebUser.CurrentUser.MailAddress.Split('@')[1];
        DataSet ds = Mcsp.McDomainUserSelectAll2(conn, WebUser.CurrentUser.DomainID);
        DataRow[] rows = ds.Tables[0].Select("", "du_name ASC");
        foreach (DataRow row in rows)
        {
            Mcsp.UserStatusFlag statusFlag = (Mcsp.UserStatusFlag)row["du_status"];
            if ((statusFlag & Mcsp.UserStatusFlag.Use) > 0 && (statusFlag & Mcsp.UserStatusFlag.OnlyOut) == 0)
            {
                string displayName = row["du_name"] as string;
                string mailAddr = string.Format("{0}@{1}", row["du_userId"] as string, domain);
                list.Add(new Recipient(displayName, mailAddr));
            }
        }

        ds = Mcsp.McMailingListSelectAll(conn, WebUser.CurrentUser.DomainID);
        rows = ds.Tables[0].Select("", "ml_name ASC");
        foreach (DataRow row in rows)
        {
            string displayName = row["ml_name"] as string;
            string mailAddr = string.Format("{0}@{1}", row["ml_mailId"] as string, domain);
            list.Add(new Recipient(displayName, mailAddr));
        }
        return list;
    }

    private static void LoadUserContacts(RecipientCollection rcptList)
    {
        // 개인 주소록은 캐시하지 않는다.
        UserAddressBook userAddrBook = new UserAddressBook(WebUser.CurrentUser.DomainUserID);
        foreach (AddressBook addrBook in userAddrBook.MyAddressBooks)
        {
            AddressBookFolder folder = addrBook.RootFolder;
            Contact[] contacts = folder.GetContacts();
            foreach (Contact contact in contacts)
            {
                string displayName = contact.DisplayName;
                string[] mailAddrs = { contact.Email, contact.Email2, contact.Email3 };
                foreach (string mailAddr in mailAddrs)
                {
                    if (mailAddr != "") rcptList.Add(new Recipient(displayName, mailAddr));
                }
            }
            TraverseSubFolders(folder, rcptList);
        }
    }

    private static void LoadSharedContacts(RecipientCollection rcptList)
    {
        if (AppSetting.RcptAutoCompleteCacheTimeMin == 0)
        {
            UserAddressBook userAddrBook = new UserAddressBook(WebUser.CurrentUser.DomainUserID);
            foreach (AddressBook shareBook in userAddrBook.ShareAddressBooks)
            {
                if (shareBook.AccessFlag != AddressBook.RsAccessFlag.None)
                {
                    AddressBookFolder folder = shareBook.RootFolder;
                    rcptList.AddRange(LoadSharedContactsFromDB(folder));
                }
            }
        }
        else
        {
            HttpContext httpContext = HttpContext.Current;
            UserAddressBook userAddrBook = new UserAddressBook(WebUser.CurrentUser.DomainUserID);
            foreach (AddressBook shareBook in userAddrBook.ShareAddressBooks)
            {
                if (shareBook.AccessFlag != AddressBook.RsAccessFlag.None)
                {
                    AddressBookFolder folder = shareBook.RootFolder;
                    // 공유 주소록은 캐시한다.
                    string cacheKey = "AutoCmplShareAddrBook:" + shareBook.ID.ToString();
                    RecipientCollection list = (RecipientCollection)httpContext.Cache[cacheKey];
                    if (list == null)
                    {
                        lock (_thisLock4SharedAddrBook)
                        {
                            list = (RecipientCollection)httpContext.Cache[cacheKey];
                            if (list == null)
                            {
                                list = LoadSharedContactsFromDB(folder);
                                httpContext.Cache.Insert(cacheKey, list, null, DateTime.UtcNow.AddMinutes(AppSetting.RcptAutoCompleteCacheTimeMin), System.Web.Caching.Cache.NoSlidingExpiration);
                            }
                        }
                    }
                    rcptList.AddRange(list);
                }
            }
        }
    }

    private static RecipientCollection LoadSharedContactsFromDB(AddressBookFolder folder)
    {
        RecipientCollection list = new RecipientCollection();
        Contact[] contacts = folder.GetContacts();
        foreach (Contact contact in contacts)
        {
            string displayName = contact.DisplayName;
            string[] mailAddrs = { contact.Email, contact.Email2, contact.Email3 };
            foreach (string mailAddr in mailAddrs)
            {
                if (mailAddr != "") list.Add(new Recipient(displayName, mailAddr));
            }
        }
        TraverseSubFolders(folder, list);
        return list;
    }

    private static void TraverseSubFolders(AddressBookFolder folder, RecipientCollection rcptList)
    {
        foreach (AddressBookFolder subfolder in folder.SubFolders)
        {
            Contact[] contacts = subfolder.GetContacts();
            foreach (Contact contact in contacts)
            {
                string displayName = contact.DisplayName;
                string[] mailAddrs = { contact.Email, contact.Email2, contact.Email3 };
                foreach (string mailAddr in mailAddrs)
                {
                    if (mailAddr != "") rcptList.Add(new Recipient(displayName, mailAddr));
                }
            }
            TraverseSubFolders(subfolder, rcptList);
        }
    }

    private static void LoadOrganization(RecipientCollection rcptList)
    {
        if (GlobalConfig.SchemaVersion < 731) return;

        SqlConnection conn = new SqlConnection(GlobalConfig.ConnString);
        if (AppSetting.RcptAutoCompleteCacheTimeMin == 0)
        {
            UserAddressBook userAddrbook = new UserAddressBook(WebUser.CurrentUser.DomainUserID);
            foreach (Organization orgz in userAddrbook.Organizations)
            {
                if (orgz.AccessFlag != Organization.RsAccessFlag.None)
                {
                    rcptList.AddRange(LoadOrganizationFromDB(conn, orgz.ID));
                }
            }
        }
        else
        {
            HttpContext httpContext = HttpContext.Current;
            UserAddressBook userAddrbook = new UserAddressBook(WebUser.CurrentUser.DomainUserID);
            foreach (Organization orgz in userAddrbook.Organizations)
            {
                if (orgz.AccessFlag != Organization.RsAccessFlag.None)
                {
                    // 공유 조직도 외부 메일 주소는 캐시한다.
                    string cacheKey = "AutoCmplOrgz:" + orgz.ID.ToString();
                    RecipientCollection list = (RecipientCollection)httpContext.Cache[cacheKey];
                    if (list == null)
                    {
                        lock (_thisLock4Organization)
                        {
                            list = (RecipientCollection)httpContext.Cache[cacheKey];
                            if (list == null)
                            {
                                list = LoadOrganizationFromDB(conn, orgz.ID);
                                httpContext.Cache.Insert(cacheKey, list, null, DateTime.UtcNow.AddMinutes(AppSetting.RcptAutoCompleteCacheTimeMin), System.Web.Caching.Cache.NoSlidingExpiration);
                            }
                        }
                    }
                    rcptList.AddRange(list);
                }
            }
        }
    }

    private static RecipientCollection LoadOrganizationFromDB(SqlConnection conn, Guid orgzId)
    {
        RecipientCollection list = new RecipientCollection();
        if (GlobalConfig.SchemaVersion < 751)
        {
            string domainName = WebUser.CurrentUser.MailAddress.Substring(WebUser.CurrentUser.MailAddress.IndexOf('@') + 1);
            DataSet ds = Mcsp.McOrganizationSelect4AutoCmplOld(conn, orgzId);
            foreach (DataRow row in ds.Tables[0].Rows)
            {
                string account = row["du_userId"] as string;
                string name = row["orz_name"] as string;
                string title = McspUtil.IsNull(row["ort_name"], "");
                string displayName = (title.Length > 0) ? title + " " + name : name;
                string mailAddr = string.Format("{0}@{1}", account, domainName);
                list.Add(new Recipient(displayName, mailAddr));
            }
        }
        else
        {
            DataSet ds = Mcsp.McOrganizationSelect4AutoCmpl(conn, orgzId);
            foreach (DataRow row in ds.Tables[0].Rows)
            {
                string name = row["orz_name"] as string;
                string title = row["ort_name"] as string;
                string part = row["orz_partname"] as string;
                string displayName = string.Format("{0}/{1}", part, (title.Length > 0) ? title + " " + name : name);
                string mailAddr = row["orz_email"] as string;
                list.Add(new Recipient(displayName, mailAddr));
            }
        }
        return list;
    }

    private static void LoadExternalMailAddressFromOrgz(RecipientCollection rcptList)
    {
        if (GlobalConfig.SchemaVersion < 731) return;

        SqlConnection conn = new SqlConnection(GlobalConfig.ConnString);
        if (AppSetting.RcptAutoCompleteCacheTimeMin == 0)
        {
            UserAddressBook userAddrbook = new UserAddressBook(WebUser.CurrentUser.DomainUserID);
            foreach (Organization orgz in userAddrbook.Organizations)
            {
                if (orgz.AccessFlag != Organization.RsAccessFlag.None)
                {
                    rcptList.AddRange(LoadExternalMailAddressFromOrgzFromDB(conn, orgz.ID));
                }
            }
        }
        else
        {
            HttpContext httpContext = HttpContext.Current;
            UserAddressBook userAddrbook = new UserAddressBook(WebUser.CurrentUser.DomainUserID);
            foreach (Organization orgz in userAddrbook.Organizations)
            {
                if (orgz.AccessFlag != Organization.RsAccessFlag.None)
                {
                    // 공유 조직도 외부 메일 주소는 캐시한다.
                    string cacheKey = "AutoCmplExtMail:" + orgz.ID.ToString();
                    RecipientCollection list = (RecipientCollection)httpContext.Cache[cacheKey];
                    if (list == null)
                    {
                        lock (_thisLock4ExtMailAddr)
                        {
                            list = (RecipientCollection)httpContext.Cache[cacheKey];
                            if (list == null)
                            {
                                list = LoadExternalMailAddressFromOrgzFromDB(conn, orgz.ID);
                                httpContext.Cache.Insert(cacheKey, list, null, DateTime.UtcNow.AddMinutes(AppSetting.RcptAutoCompleteCacheTimeMin), System.Web.Caching.Cache.NoSlidingExpiration);
                            }
                        }
                    }
                    rcptList.AddRange(list);
                }
            }
        }
    }

    private static RecipientCollection LoadExternalMailAddressFromOrgzFromDB(SqlConnection conn, Guid orgzId)
    {
        RecipientCollection list = new RecipientCollection();
        DataSet ds = Mcsp.McOrganizationSelectByExternal(conn, orgzId);
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            string displayName = row["orz_name"] as string;
            string mailAddr = row["orz_extmailaddr"] as string;
            list.Add(new Recipient(displayName, mailAddr));
        }
        return list;
    }

    private static void ExceptAddress(RecipientCollection rcptList)
    {
        string xmlFile = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/AutoCmplExcept.xml");
        XmlDocument xml = new XmlDocument();
        try
        {
            xml.Load(xmlFile);
            foreach (XmlNode childNode in xml.DocumentElement.ChildNodes)
            {
                if (childNode.Name == "email" && childNode.InnerText.Length > 0)
                {
                    string exceptEmail = childNode.InnerText.Trim();
                    rcptList.RemoveAll(r => string.Compare(r.Address, exceptEmail, true) == 0);
                }
            }
        }
        catch
        {
        }
    }
}