using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Bitrix.UI;
using Bitrix.IBlock;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Bitrix.Components;
using Bitrix.DataLayer;
using Bitrix.Services.Text;
using Bitrix.Security;
using Bitrix.Components.Editor;
using Bitrix.Services;
using Bitrix.DataTypes;
using Bitrix.Configuration;
using Bitrix.IO;

namespace Bitrix.IBlock.Components
{
    public partial class IBlockMyElementListComponent : Bitrix.UI.BXComponent
    {
        #region Enum
        public enum MannerOfUserAssociation
        {
            NoBody = 1,
            CreatedBy,
            IBlockProperty
        }

        public enum MannerOfIssueModificationPermission
        {
            Active = 1,
            NotActive,
            Always
        }

       [FlagsAttribute]
        public enum Error
        {
            /// <summary>
            /// Без ошибок
            /// </summary>
            ErrNone = 0,  
            /// <summary>
            /// Не найден инфоблок
            /// </summary>
            ErrIBlockIsNotFound = 1
            /// <summary>
            /// Не найдено сво-во инфоблока
            /// </summary>
            //ErrIBlockPropertyIsNotFound
        }

        #endregion

        public class Item
        {
            public Item(BXIBlockElement element) 
            {
                if (element == null)
                    throw new ArgumentNullException("element");

                _element = element;
            }
            private BXIBlockElement _element = null;
            public BXIBlockElement Element
            {
                get { return _element; }
            }
            public int GetElementId() 
            {
                return _element.Id;
            }
            public string GetElementName()
            {
                return _element.Name;
            }
            public string GetElementPreviewText()
            {
                return _element.PreviewText;
            }
            public string GetElementDetailText()
            {
                return _element.DetailText;
            }
            public DateTime GetElementCreationDateTime()
            {
                return _element.CreateDate;
            }

        }

        #region Events

        protected override void OnInit(EventArgs e)
        {
            CacheMode = BXCacheMode.None;
            Page.LoadComplete += new EventHandler(Page_LoadComplete);
            base.OnInit(e);
        }

        void Page_LoadComplete(object sender, EventArgs e)
        {
            BXPrincipal user = GetUser();
            if (user == null)
                return;
            BXPagingParams pagingParams = PreparePagingParams();
            //if (IsCached(((BXPrincipal)Page.User).GetAllRoles(true), pagingParams))
            //{
            //    SetTemplateCachedData();
            //    return;
            //}

            EnsureIBlockDataLoaded();
            if ((ComponentErrors & Error.ErrIBlockIsNotFound) == Error.ErrIBlockIsNotFound)
                return;

            if (!IsUserAutorizedToManageMyElementList())
                return;

            BXFilter elementFilter = new BXFilter(
                //new BXFilterItem(BXIBlockElement.Fields.Active, BXSqlFilterOperators.Equal, "Y"),
                new BXFilterItem(BXIBlockElement.Fields.IBlock.ID, BXSqlFilterOperators.Equal, IBlockId)
                //new BXFilterItem(BXIBlockElement.Fields.CheckPermissions, BXSqlFilterOperators.Equal, "Y")
            );

            MannerOfUserAssociation mannerOfUserAssociation = UserAssociation;
            int userID = ((BXIdentity)user.Identity).Id;
            switch (mannerOfUserAssociation)
            {
                case MannerOfUserAssociation.CreatedBy:
                    elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.CreatedBy, BXSqlFilterOperators.Equal, userID));
                    break;
                case MannerOfUserAssociation.IBlockProperty:
                    {
                        bool isHandled = false;
                        string userAssociatedByCustomIBlockProperty = Parameters.Get<string>("UserAssociatedByCustomIBlockProperty", string.Empty);
                        if (!string.IsNullOrEmpty(userAssociatedByCustomIBlockProperty))
                        {
                            BXCustomFieldCollection customFields = IBlock != null ? IBlock.CustomFields : null;
                            BXCustomField field = null;
                            try
                            {
                                field = customFields[userAssociatedByCustomIBlockProperty];
                            }
                            catch (KeyNotFoundException /*exc*/) { }
                            if (field != null)
                            {
                                elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.GetCustomField(IBlockId, field.Name), BXSqlFilterOperators.Equal, userID));
                                isHandled = true;
                            }
                        }

                        if (!isHandled)
                            elementFilter.Add(new BXFilterItem(BXIBlockElement.Fields.CreatedBy, BXSqlFilterOperators.Equal, userID));
                    }
                    break;
                case MannerOfUserAssociation.NoBody:
                    break;
                default:
                    throw new InvalidOperationException(string.Format("Value '{0}' is not supported in current context!", Enum.GetName(typeof(MannerOfUserAssociation), mannerOfUserAssociation)));
            }


            Dictionary<string, BXCustomField> iblockCustomFields = new Dictionary<string, BXCustomField>(IBlock.CustomFields.Count);
            foreach (BXCustomField field in IBlock.CustomFields)
                iblockCustomFields[field.CorrectedName] = field;

            //Sorting
            BXOrderBy elementOrderBy = new BXOrderBy();
            string sortBy = Parameters.Get<string>("SortBy", "Id");
            string sortOrder = Parameters.Get<string>("SortOrder", "Desc");

            if (sortBy.StartsWith("-", StringComparison.OrdinalIgnoreCase))
            {
                sortBy = sortBy.Substring(1).ToUpper();
                if (iblockCustomFields.ContainsKey(sortBy))
                    elementOrderBy.Add(BXIBlockElement.Fields.GetCustomField(IBlockId, sortBy), sortOrder);
            }
            else
                elementOrderBy.Add(BXIBlockElement.Fields, sortBy, sortOrder);

            //Paging
            bool isLegalPage;
            BXQueryParams queryParams = PreparePaging(
                pagingParams,
                delegate { return BXIBlockElement.Count(elementFilter); },
                new BXParamsBag<object>(),
                out isLegalPage
            );

            if (!Parameters.Get<bool>("PagingAllow"))
                queryParams = new BXQueryParams(new BXPagingOptions(0, Parameters.Get<int>("PagingRecordsPerPage", 10)));
            //else if (!isLegalPage)
            //    AbortCache();

            BXIBlockElementCollection col = BXIBlockElement.GetList(elementFilter, elementOrderBy, null, queryParams, BXTextEncoder.HtmlTextEncoder);
            int colLength = col != null ? col.Count : 0;
            _items = new List<Item>();
            for (int i = 0; i < colLength; i++)
                _items.Add(new Item(col[i]));
        }

        protected override void OnLoad(EventArgs e)
        {
            IncludeComponentTemplate();
            base.OnLoad(e);
        }
        #endregion

        #region Service

        private BXPrincipal GetUser() 
        {
            return Context.User as BXPrincipal;
        }
        public bool IsUserAutorizedToManageMyElementList() 
        {
            BXPrincipal user = GetUser();
            if (user == null)
                return false;

            List<string> rolesAuthorizedToManageList = Parameters.GetListString("RolesAuthorizedToManage");
            if (rolesAuthorizedToManageList == null || rolesAuthorizedToManageList.Count == 0)
                return IBlock != null ? IBlock.IsUserCanOperate(BXIBlock.Operations.IBlockPublicRead) : false;

            string[] userRoleCollection = user.GetAllRoles();
            foreach (string userRole in userRoleCollection)
            {
                if (rolesAuthorizedToManageList.Contains(userRole))
                    return true;
            }
            return false;
        }

        private bool _isIBlockDataLoaded = false;
        private void EnsureIBlockDataLoaded() 
        {
            if (_isIBlockDataLoaded)
                return;
            BXIBlockCollection iblockCollection = BXIBlock.GetList(
                new BXFilter(
                    new BXFilterItem(BXIBlock.Fields.Active, BXSqlFilterOperators.Equal, "Y"),
                //new BXFilterItem(BXIBlock.Fields.CheckPermissions, BXSqlFilterOperators.Equal, "Y"),
                    new BXFilterItem(BXIBlock.Fields.ID, BXSqlFilterOperators.Equal, IBlockId)
                ),
                null,
                null,
                null,
                BXTextEncoder.HtmlTextEncoder
            );

            if (iblockCollection == null || iblockCollection.Count < 1)
                GenerateNotFoundError(Error.ErrIBlockIsNotFound);
            else
            {
                IBlock = iblockCollection[0];
                IBlockTypeId = IBlock.TypeId;
                IBlockName = IBlock.Name;
            }

            _isIBlockDataLoaded = true;
        }

        //private void SetTemplateCachedData(){}
        private string PrepareUrl(string url) 
        {
            if (string.IsNullOrEmpty(url))
                return string.Empty;

            if (url.StartsWith("http"))
                return url;

            int whatInd = url.IndexOf('?');
            string query = whatInd >= 0 ? url.Substring(whatInd) : string.Empty;
            string path = whatInd >= 0 ? url.Substring(0, whatInd) : url;
            if (string.IsNullOrEmpty(path))
                path = Request.AppRelativeCurrentExecutionFilePath;
            else if (!VirtualPathUtility.IsAbsolute(path))
                path = VirtualPathUtility.Combine(Request.AppRelativeCurrentExecutionFilePath, path);

            return string.Concat(path, query);
        }

        public string GetUrlForElementCreation() 
        {
            string urlPattern = ElementCreationUrl;
            BXParamsBag<object> replaceItems = new BXParamsBag<object>();
            replaceItems.Add("IblockId", IBlockId);
            replaceItems.Add("IBLOCK_ID", IBlockId);

            return PrepareUrl(MakeLink(urlPattern, replaceItems));
        }

        public string GetUrlForModification(int elementID)
        {
            //string urlPattern = EnableSef ? ElementModificationUrlSef : ElementModificationUrl;
            if (!IsElementModificationAllowed(elementID))
                return string.Empty;
            string urlPattern = ElementModificationUrl;
            if (string.IsNullOrEmpty(urlPattern))
                return string.Empty;
            BXParamsBag<object> replaceItems = new BXParamsBag<object>();
            replaceItems.Add("IblockId", IBlockId);
            replaceItems.Add("IBLOCK_ID", IBlockId);
            replaceItems.Add("ELEMENT_ID", elementID);
            replaceItems.Add("ElementId", elementID);

            return PrepareUrl(MakeLink(urlPattern, replaceItems));
        }

        /// <summary>
        /// Запрос разрешения на редактирование эл-та
        /// </summary>
        /// <param name="elementID"></param>
        /// <returns></returns>
        public bool IsElementModificationAllowed(int elementID) 
        {
            if (!PermitOfModification)
                return false;

            MannerOfIssueModificationPermission mp = IssueModificationPermission;
            if (mp == MannerOfIssueModificationPermission.Always)
                return true;

            Item item = GetItemById(elementID);
            if(item == null)
                throw new InvalidOperationException("Item is not found in list!");

            if (mp == MannerOfIssueModificationPermission.Active)
                return item.Element.Active;
            else if (mp == MannerOfIssueModificationPermission.NotActive)
                return !item.Element.Active;
            else
                return false;
        }

        /// <summary>
        /// Запрос разрешения на удаление эл-та
        /// </summary>
        /// <param name="elementID"></param>
        /// <returns></returns>
        public bool IsElementDeletionAllowed(int elementID) 
        {
            return PermitOfDeletion;
        }

        public void DeleteElement(int elementID) 
        {
            if (!IsUserAutorizedToManageMyElementList())
                throw new InvalidOperationException("User is not authorized!");
            //---
            if (!PermitOfDeletion)
            {
                Response.Redirect(Request.RawUrl);
                return;
            }

            BXIBlockElement element = BXIBlockElement.GetById(elementID);
            //BXIBlockElement element = GetItemById(elementID);
            if (element == null)
            {
                Response.Redirect(Request.RawUrl);
                return;
            }

            bool aboutOwnerShip = false;

            MannerOfUserAssociation mannerOfUserAssociation = UserAssociation;
            BXPrincipal user = GetUser();
            if(user != null)
                switch (mannerOfUserAssociation)
                {
                    case MannerOfUserAssociation.CreatedBy:
                        aboutOwnerShip = element.CreatedByUser.UserId == ((BXIdentity)user.Identity).Id;
                        break;
                    case MannerOfUserAssociation.IBlockProperty:
                        {
                            BXCustomField field;
                            BXCustomProperty prop;
                            string userAssociatedByCustomIBlockProperty = Parameters.Get<string>("UserAssociatedByCustomIBlockProperty", string.Empty);
                            if (!string.IsNullOrEmpty(userAssociatedByCustomIBlockProperty) &&  
                                element.CustomFields.TryGetValue("userAssociatedByCustomIBlockProperty", out field) &&
                                element.CustomValues.TryGetValue("userAssociatedByCustomIBlockProperty", out prop)
                                )
                            {
                                try
                                {
                                    aboutOwnerShip = string.Equals(field.CustomTypeId, "Bitrix.System.Int", StringComparison.Ordinal) && Convert.ToInt32(prop.Value) == ((BXIdentity)user.Identity).Id;
                                }
                                catch(InvalidCastException /*exc*/){}
                            }
                        }
                        break;
                    case MannerOfUserAssociation.NoBody:
                        aboutOwnerShip = true;
                        break;
                }

            if (aboutOwnerShip)
            {
                //BXIBlockElement.Delete(new BXFilter(new BXFilterItem(BXIBlockElement.Fields.ID, BXSqlFilterOperators.Equal, elementID)));
                BXIBlockElement el = BXIBlockElement.GetById(elementID);
                if (el != null)
                    el.Delete();
            }
            Response.Redirect(Request.RawUrl);
        }

        private Error _err = Error.ErrNone;
        /// <summary>
        /// Ошибка
        /// </summary>
        public Error ComponentErrors
        {
            get { return _err; }
        }

        private void GenerateNotFoundError(Error error)
        {
            _err |= error;

            AbortCache();

            ScriptManager ajax = Page != null ? ScriptManager.GetCurrent(Page) : null;
            if (!IsComponentDesignMode && BXConfigurationUtility.ShowMode == BXShowMode.View && (ajax == null || !ajax.IsInAsyncPostBack))
                BXError404Manager.Set404Status(Response);
        }

        private Item GetItemById(int elementID) 
        {
            if (_items == null || _items.Count == 0)
                return null;
            int itemInd = _items.FindIndex(
                    delegate(Item obj) { return obj.GetElementId() == elementID; }
                    );
			return itemInd >= 0 ? _items[itemInd] : null;
        }

        #endregion

        #region Properties
        #region IBlock

        public int IBlockId
        {
            get { return Parameters.Get<int>("IBlockId"); }
        }

        protected BXIBlock _iblock;
        public BXIBlock IBlock
        {
            get { return _iblock; }
            protected set { _iblock = value; }
        }

        public string IBlockName
        {
            get { return ComponentCache.Get<string>("IBlockName", string.Empty); }
            protected set { ComponentCache["IBlockName"] = value; }
        }

        public string IBlockElementName
        {
            get { return ComponentCache.Get<string>("IBlockElementName", String.Empty); }
            protected set { ComponentCache["IBlockElementName"] = value; }
        }

        public string IBlockSectionName
        {
            get { return ComponentCache.Get<string>("IBlockSectionName", String.Empty); }
            protected set { ComponentCache["IBlockSectionName"] = value; }
        }

        public int IBlockTypeId
        {
            get { return ComponentCache.Get<int>("IBlockTypeId"); }
            protected set { ComponentCache["IBlockTypeId"] = value; }
        }

        public MannerOfUserAssociation UserAssociation
        {
            get 
            {
                object rObj = null;
                if (ComponentCache.TryGetValue("MannerOfUserAssociation", out rObj))
                    return (MannerOfUserAssociation)rObj;

                string rStr = Parameters.Get("MannerOfUserAssociation", string.Empty);
                MannerOfUserAssociation r = !string.IsNullOrEmpty(rStr) ? (MannerOfUserAssociation)Enum.Parse(typeof(MannerOfUserAssociation), rStr) : MannerOfUserAssociation.CreatedBy;
                ComponentCache["MannerOfUserAssociation"] = r;
                return r;
            }
        }

        public MannerOfIssueModificationPermission IssueModificationPermission
        {
            get 
            {
                object rObj = null;
                if (ComponentCache.TryGetValue("MannerOfIssueModificationPermission", out rObj))
                    return (MannerOfIssueModificationPermission)rObj;

                string rStr = Parameters.Get("MannerOfIssueModificationPermission", string.Empty);
                MannerOfIssueModificationPermission r = !string.IsNullOrEmpty(rStr) ? (MannerOfIssueModificationPermission)Enum.Parse(typeof(MannerOfIssueModificationPermission), rStr) : MannerOfIssueModificationPermission.Always;
                ComponentCache["MannerOfIssueModificationPermission"] = r;
                return r;
            }
        }

        public bool PermitOfCreation
        {
            get
            {
                object rObj = null;
                if (ComponentCache.TryGetValue("PermitOfCreation", out rObj))
                    return (bool)rObj;

                bool r = Parameters.Get<bool>("PermitOfCreation", false);
                ComponentCache["PermitOfCreation"] = r;
                return r;
            }
        }

        public bool PermitOfModification 
        {
            get 
            {
                object rObj = null;
                if (ComponentCache.TryGetValue("PermitOfModification", out rObj))
                    return (bool)rObj;

                bool r = Parameters.Get<bool>("PermitOfModification", false);
                ComponentCache["PermitOfModification"] = r;
                return r;
            }
        }

        public bool PermitOfDeletion
        {
            get
            {
                object rObj = null;
                if (ComponentCache.TryGetValue("PermitOfDeletion", out rObj))
                    return (bool)rObj;

                bool r = Parameters.Get("PermitOfDeletion", false);
                ComponentCache["PermitOfDeletion"] = r;
                return r;
            }
        }


        //public bool EnableSef 
        //{
        //    get { return Parameters.Get<bool>("EnableSEF", false); }
        //}

        //public string ElementModificationUrlSef
        //{
        //    get
        //    {
        //        return Parameters.Get<string>("ElementModificationUrlSef", "/myElementList-#ElementId#/");
        //    }
        //}

        public string ElementCreationUrl
        {
            get
            {
                return Parameters.Get<string>("ElementCreationUrl", "./edit.aspx");
            }
        }

        public string ElementModificationUrl
        {
            get
            {
                return Parameters.Get<string>("ElementModificationUrl", "./edit.aspx?elementId=#ElementId#");
            }
        }

        public string ElementCreationUrlTitle
        {
            get 
            {
                return Parameters.Get<string>("ElementCreationUrlTitle", GetMessageRaw("TitleAddElement"));
            }
        }

        #endregion
        #region Items
        protected List<Item> _items = null;
        public IList<Item> Items
        {
            get 
            {
                if (_items != null)
                    return new ReadOnlyCollection<Item>(_items);
                return new List<Item>(); 
            }
        }
        #endregion
        #endregion

        #region Component
        protected override void PreLoadComponentDefinition()
        {
            Title = GetMessageRaw("Title");
            Description = GetMessageRaw("Description");
            Icon = "images/iblock_my_el_list.gif";
            Group = new BXComponentGroup("iblock.elements", GetMessageRaw("Group"), 100, BXComponentGroup.Content);

            BXCategory dataSourceCategory = BXCategory.DataSource;
            BXCategory mainCategory = BXCategory.Main;
            BXCategory sefCategory = BXCategory.Sef;
            BXCategory acessCategory = new BXCategory(GetMessageRaw("Category.Access"), "ACCESS", 110);
            BXCategory additionalSettingsCategory = BXCategory.AdditionalSettings;

            ParamsDefinition.Add(BXParametersDefinition.Paging);
            ParamsDefinition.Add(BXParametersDefinition.PagingUrl);

            //BXParamsBag<BXParam> sefParBag = BXParametersDefinition.Sef;
            //sefParBag["EnableSEF"].ClientSideAction = new ParamClientSideActionGroupViewSwitch(ClientID, "EnableSEF", "Sef", "NonSef");
            //sefParBag["SEFFolder"].ClientSideAction = new ParamClientSideActionGroupViewMember(ClientID, "SEFFolder", new string[] { "Sef" });
            //ParamsDefinition.Add(sefParBag);

            ParamsDefinition.Add(
                "IBlockTypeId",
                new BXParamSingleSelection(
                    GetMessageRaw("InfoBlockType"),
                    String.Empty,
                    mainCategory
                )
            );

            ParamsDefinition.Add(
                "IBlockId",
                new BXParamSingleSelection(
                    GetMessageRaw("InfoBlockCode"),
                    String.Empty,
                    mainCategory
                )
            );

            ParamsDefinition.Add(
                "SortBy",
                new BXParamSingleSelection(
                    GetMessageRaw("SortBy"),
                    "Id",
                    dataSourceCategory
                )
            );

            ParamsDefinition.Add(
                "SortOrder",
                new BXParamSort(
                    GetMessageRaw("SortOrder"),
                    true,
                    dataSourceCategory
                )
            );

            ParamsDefinition.Add(
                "ElementCreationUrl",
                new BXParamText(
                    GetMessageRaw("ElementCreationUrl"),
                    "./edit.aspx",
                    sefCategory
                //new ParamClientSideActionGroupViewMember(ClientID, "ElementCreationUrl", new string[] { "NonSef" })
                ));

            ParamsDefinition.Add(
                "ElementCreationUrlTitle",
                new BXParamText(
                    GetMessageRaw("ElementCreationUrlTitle"),
                    GetMessageRaw("TitleAddElement") /*"<script type='text/javascript'>alert('Hello all!')<script>"*/,
                    additionalSettingsCategory
                ));

            ParamsDefinition.Add(
                "ElementModificationUrl",
                new BXParamText(
                    GetMessageRaw("ElementModificationUrl"),
                    "./edit.aspx?elementId=#ElementId#",
                    sefCategory
                    //new ParamClientSideActionGroupViewMember(ClientID, "ElementModificationUrl", new string[] { "NonSef" })
                ));

            //ParamsDefinition.Add(
            //    "ElementModificationUrlSef",
            //    new BXParamText(
            //        GetMessageRaw("ElementModificationUrlSef"),
            //        "/BlockId-#IblockId#/ElementId-#ElementId#/",
            //        sefCategory,
            //        new ParamClientSideActionGroupViewMember(ClientID, "ElementModificationUrlSef", new string[] { "Sef" })
            //    ));

            BXRole admin = BXRoleManager.GetById(1);

            ParamsDefinition.Add(
                "RolesAuthorizedToManage",
                new BXParamMultiSelection(
                    GetMessageRaw("RolesAuthorizedToManage"),
                    admin != null ? admin.RoleName : string.Empty,
                    acessCategory
                ));

            ParamsDefinition.Add(
                "MannerOfUserAssociation",
                new BXParamSingleSelection(
                    GetMessageRaw("MannerOfUserAssociation"),
                    Enum.GetName(typeof(MannerOfUserAssociation), MannerOfUserAssociation.CreatedBy),
                    acessCategory, 
                    null,
                    new ParamClientSideActionGroupViewSelector(ClientID, "MannerOfUserAssociation")
                ));

            ParamsDefinition.Add(
                "UserAssociatedByCustomIBlockProperty",
                new BXParamSingleSelection(
                    GetMessageRaw("UserAssociatedByCustomIBlockProperty"),
                    string.Empty,
                    acessCategory, 
                    null,
                    new ParamClientSideActionGroupViewMember(ClientID, "UserAssociatedByCustomIBlockProperty", new string[] { Enum.GetName(typeof(MannerOfUserAssociation), MannerOfUserAssociation.IBlockProperty) }) 
                ));

            ParamsDefinition.Add(
                "PermitOfCreation",
                new BXParamYesNo(
                    GetMessageRaw("PermitOfCreation"),
                    false,
                    acessCategory
                ));

            ParamsDefinition.Add(
                "PermitOfModification",
                new BXParamYesNo(
                    GetMessageRaw("PermitOfModification"),
                    false,
                    acessCategory,
                    new ParamClientSideActionGroupViewSwitch(ClientID, "PermitOfModification", "PermitOfElementModification", string.Empty)
                ));

            ParamsDefinition.Add(
                "MannerOfIssueModificationPermission",
                new BXParamSingleSelection(
                    GetMessageRaw("MannerOfIssueModificationPermission"),
                    Enum.GetName(typeof(MannerOfIssueModificationPermission), MannerOfIssueModificationPermission.Active),
                    acessCategory,
                    null,
                    new ParamClientSideActionGroupViewMember(ClientID, "MannerOfIssueModificationPermission", new string[] { "PermitOfElementModification" })
                ));

            ParamsDefinition.Add(
                "PermitOfDeletion",
                new BXParamYesNo(
                    GetMessageRaw("PermitOfDeletion"),
                    false,
                    acessCategory
                ));
        }

        protected override void LoadComponentDefinition()
        {
            #region Properties
            List<BXParamValue>  properties = new List<BXParamValue>(),
                                propertiesForUserReference = new List<BXParamValue>();
            int selectedIblockId = 0;
            if (Parameters.ContainsKey("IBlockId"))
                int.TryParse(Parameters["IBlockId"], out selectedIblockId);

            if (selectedIblockId > 0)
            {
                BXCustomFieldCollection customFields = BXIBlock.GetCustomFields(selectedIblockId);
                foreach (BXCustomField customField in customFields)
                {
                    string title = BXTextEncoder.HtmlTextEncoder.Decode(customField.EditFormLabel);
                    string code = customField.Name.ToUpper();   
                    properties.Add(new BXParamValue(title, code));
                    if (string.Equals(customField.CustomTypeId, "Bitrix.System.Int", StringComparison.Ordinal))
                        propertiesForUserReference.Add(new BXParamValue(title, code));
                }
            }
            #endregion

            #region Iblock type
            List<BXParamValue> typeParamValue = new List<BXParamValue>();
            typeParamValue.Add(new BXParamValue(GetMessageRaw("SelectIBlockType"), ""));

            BXIBlockTypeCollection iblockTypes = BXIBlockType.GetList(null, new BXOrderBy(new BXOrderByPair(BXIBlockType.Fields.Name, BXOrderByDirection.Asc)), null, null, BXTextEncoder.EmptyTextEncoder);
            foreach (BXIBlockType iblockType in iblockTypes)
                typeParamValue.Add(new BXParamValue(iblockType.Translations[BXLoc.CurrentLocale].Name, iblockType.Id.ToString()));

            ParamsDefinition["IBlockTypeId"].Values = typeParamValue;
            ParamsDefinition["IBlockTypeId"].RefreshOnDirty = true;
            #endregion

            #region Iblock
            int selectedIBlockType = 0;
            if (Parameters.ContainsKey("IBlockTypeId"))
                int.TryParse(Parameters["IBlockTypeId"], out selectedIBlockType);

            BXFilter filter = new BXFilter();
            if (selectedIBlockType > 0)
                filter.Add(new BXFilterItem(BXIBlock.Fields.Type.ID, BXSqlFilterOperators.Equal, selectedIBlockType));
            if (!string.IsNullOrEmpty(DesignerSite))
                filter.Add(new BXFilterItem(BXIBlock.Fields.Sites.SiteId, BXSqlFilterOperators.Equal, DesignerSite));

            List<BXParamValue> iblockParamValue = new List<BXParamValue>();
            iblockParamValue.Add(new BXParamValue(GetMessageRaw("SelectIBlockID"), string.Empty));
            BXIBlockCollection iblocks = BXIBlock.GetList(filter, new BXOrderBy(new BXOrderByPair(BXIBlock.Fields.Name, BXOrderByDirection.Asc)), null, null, BXTextEncoder.EmptyTextEncoder);
            foreach (BXIBlock iblock in iblocks)
                iblockParamValue.Add(new BXParamValue(iblock.Name, iblock.Id.ToString()));

            ParamsDefinition["IBlockId"].Values = iblockParamValue;
            ParamsDefinition["IBlockId"].RefreshOnDirty = true;
            #endregion

            #region Sorting
            List<BXParamValue> sortingFields = new List<BXParamValue>();
            sortingFields.Add(new BXParamValue(GetMessageRaw("ElementID"), "ID"));
            sortingFields.Add(new BXParamValue(GetMessageRaw("ElementName"), "Name"));
            sortingFields.Add(new BXParamValue(GetMessageRaw("ActiveFromDate"), "ActiveFromDate"));
            sortingFields.Add(new BXParamValue(GetMessageRaw("ActiveUntilDate"), "ActiveToDate"));
            sortingFields.Add(new BXParamValue(GetMessageRaw("SortIndex"), "Sort"));
            sortingFields.Add(new BXParamValue(GetMessageRaw("DateOfModification"), "UpdateDate"));
            sortingFields.AddRange(properties);

            ParamsDefinition["SortBy"].Values = sortingFields;
            #endregion

            #region Access
            //RolesAuthorizedToManage
            IList<BXParamValue> authRolesValues = ParamsDefinition["RolesAuthorizedToManage"].Values;
            if (authRolesValues.Count > 0)
                authRolesValues.Clear();

            BXRoleCollection roles = BXRoleManager.GetList(new BXFormFilter(new BXFormFilterItem("Active", true, BXSqlFilterOperators.Equal)), new BXOrderBy_old("RoleName", "Asc"));
            for (int i = 0; i < roles.Count; i++) 
            {
                BXRole role = roles[i];
                authRolesValues.Add(new BXParamValue(role.Title, role.RoleName));
            }
            //---
            //MannerOfIssueModificationPermission
            IList<BXParamValue> manOfIssueModificationPermissionValues = ParamsDefinition["MannerOfIssueModificationPermission"].Values;
            if (manOfIssueModificationPermissionValues.Count > 0)
                manOfIssueModificationPermissionValues.Clear();

            string[] manOfIssueModificationPermissionNames  = Enum.GetNames(typeof(MannerOfIssueModificationPermission));
            int manOfIssueModificationPermissionNamesCount = manOfIssueModificationPermissionNames != null ? manOfIssueModificationPermissionNames.Length : 0;
            for (int j = 0; j < manOfIssueModificationPermissionNamesCount; j++) 
            {
                string name = manOfIssueModificationPermissionNames[j];
                manOfIssueModificationPermissionValues.Add(new BXParamValue(GetMessageRaw(string.Concat("MannerOfIssueModificationPermission", name)), name));
            }
            //---
            //MannerOfUserAssociation
            IList<BXParamValue> mannerOfUserAssociationValues = ParamsDefinition["MannerOfUserAssociation"].Values;
            if (mannerOfUserAssociationValues.Count > 0)
                mannerOfUserAssociationValues.Clear();

            string[] mannerOfUserAssociationNames = Enum.GetNames(typeof(MannerOfUserAssociation));
            int mannerOfUserAssociationNamesCount = mannerOfUserAssociationNames != null ? mannerOfUserAssociationNames.Length : 0;
            for (int k = 0; k < mannerOfUserAssociationNamesCount; k++)
            {
                string name = mannerOfUserAssociationNames[k];
                mannerOfUserAssociationValues.Add(new BXParamValue(GetMessageRaw(string.Concat("MannerOfUserAssociation", name)), name));
            }
            //---
            //UserAssociatedByCustomIBlockProperty
            IList<BXParamValue> userAssociatedByCustomIBlockPropertyValues = ParamsDefinition["UserAssociatedByCustomIBlockProperty"].Values;
            if (userAssociatedByCustomIBlockPropertyValues.Count > 0)
                userAssociatedByCustomIBlockPropertyValues.Clear();

            userAssociatedByCustomIBlockPropertyValues.Add(new BXParamValue(GetMessageRaw("NotSelected"), string.Empty));
            for (int n = 0; n < propertiesForUserReference.Count; n++)
                userAssociatedByCustomIBlockPropertyValues.Add(propertiesForUserReference[n]);
            //---
            #endregion
        }

        public BXPopupMenuItem[] GetMenuItems()
        {
            EnsureIBlockDataLoaded();

            BXPopupMenuItem[] menuItems = new BXPopupMenuItem[1];

            menuItems[0] = new BXPopupMenuItem();
            menuItems[0].BackgroundImagePath = BXPath.Combine(BXComponentManager.GetFolder(Name), "/images/new_element.gif");
            menuItems[0].ID = String.Format("myElementList_new_{0}", IBlockId);
            menuItems[0].Text = String.Format(GetMessageRaw("AddNewElement"), String.IsNullOrEmpty(IBlockElementName) ? GetMessageRaw("IBlockElementName") : BXTextEncoder.HtmlTextEncoder.Decode(IBlockElementName.ToLower()));
            menuItems[0].ClientClickScript =
                String.Format(
                    "jsUtils.Redirect(arguments, '{0}?type_id={2}&iblock_id={1}&{3}={4}')",
                    VirtualPathUtility.ToAbsolute("~/bitrix/admin/IBlockElementEdit.aspx"),
                    IBlockId,
                    IBlockTypeId,
                    BXConfigurationUtility.Constants.BackUrl,
                    UrlEncode(BXSefUrlManager.CurrentUrl.PathAndQuery)
                );

            return menuItems;
        }

        /// <summary>
        /// Создание контекстного меню
        /// </summary>
        public override BXComponentPopupMenuInfo PopupMenuInfo
        {
            get
            {
                BXComponentPopupMenuInfo info = base.PopupMenuInfo;

                if (BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockAdminRead) &&
                    BXIBlock.IsUserCanOperate(IBlockId, BXIBlock.Operations.IBlockModifyElements) &&
                    ComponentErrors == Error.ErrNone)
                {
                    info.CreateCustomPopupMenuItems = delegate(BXShowMode showMode)
                    {
                        if (showMode != BXShowMode.View)
                            return GetMenuItems();
                        else
                            return null;
                    };
                }
                return info;
            }
        }
        #endregion
    }

    public class IBlockMyElementListTemplate : BXComponentTemplate<IBlockMyElementListComponent>
    {
        protected override void Render(HtmlTextWriter writer)
        {
            StartWidth = "100%";
            if (IsComponentDesignMode)
            {
                if (IsComponentDesignMode && Component.ComponentErrors != IBlockMyElementListComponent.Error.ErrNone)
                    writer.Write(BXLoc.GetMessage(Component, "YouHaveToAdjustTheComponent"));
                else if (Component.Items.Count == 0)
                {
                    writer.Write(BXLoc.GetMessage(Component, "NoData"));
                }
                else
                    base.Render(writer);
                return;
            }
            base.Render(writer);
        }
    }
}
