using System;
using Telerik.Sitefinity.Configuration;
using Telerik.Sitefinity.News.Model;
using Telerik.Sitefinity.Pages.Model;
using Telerik.Sitefinity.Security;
using Telerik.Sitefinity.Security.Configuration;
using Telerik.Sitefinity.Services;
using Telerik.Sitefinity.Workflow;
using Telerik.Sitefinity.Workflow.Model;

namespace SitefinityWebApp.CustomWorkflow
{
    public class WorkflowDefinitionSamples
    {
        private IWorkflowExecutionDefinition CreateSimpleApprovalWorkflowDefinition(Guid definitionId)
        {
            var workflowManager = WorkflowManager.GetManager();
            var backendUsersRole = Config.Get<SecurityConfig>().ApplicationRoles[SecurityConstants.AppRoles.BackendUsers];

            // "Approve" is the only level in 1-step approval process.          
            var workflowDefinition = workflowManager.CreateWorkflowDefinition(definitionId);
            workflowDefinition.Title = "1-step workflow for Bloggers";
            workflowDefinition.WorkflowType = WorkflowType.StandardOneStep;
            workflowDefinition.AllowAdministratorsToSkipWorkflow = false;
            workflowDefinition.AllowPublishersToSkipWorkflow = false;
            workflowDefinition.AllowNotes = true;
            workflowDefinition.IsActive = true;

            // Levels section
            var approvePermission = workflowManager.CreateWorkflowPermission();
            approvePermission.ActionName = "Approve";
            approvePermission.PrincipalType = WorkflowPrincipalType.Role;
            approvePermission.PrincipalId = backendUsersRole.Id.ToString();
            approvePermission.PrincipalName = backendUsersRole.Name;

            var level1 = workflowManager.CreateWorkflowLevel();
            level1.ActionName = "Approve";
            level1.Ordinal = 1;
            level1.NotifyAdministrators = true;
            level1.NotifyApprovers = true;
            level1.Permissions.Add(approvePermission);

            workflowDefinition.Levels.Add(level1);

            // Scopes section - determines whether the workflow is valid for a specific site or language
            var workflowScope1 = workflowManager.CreateWorkflowScope();
            // You can specify whether the workflow is valid for a specified site only
            // If you omit this line the workflow is valid for all sites by default
            workflowManager.Provider.AddItemLink(SystemManager.CurrentContext.CurrentSite.Id, workflowScope1);
            // You can specify whether the workflow is valid for a specified language only
            // If you omit this line the workflow is valid for all languages by default
            workflowScope1.Language = "en";

            //TypeScope section - determines whether the workflow is valid for a specific item type or specific page(s) if the item type is PageNode
            var typeScope1 = workflowManager.CreateWorkflowTypeScope();
            //Specify this workflow to be valid for Newsitems
            typeScope1.ContentType = typeof(NewsItem).FullName;


            var typeScope2 = workflowManager.CreateWorkflowTypeScope();
            //specify this workflow to be valid for Pages
            typeScope2.ContentType = typeof(PageNode).FullName;
            // If you want to specify only selected pages, pass a comma separated list of PageNode Ids to the ContentFilter
            typeScope2.ContentFilter = "";
            //Ste the IncludeChildren property to true/false to determine whether to include child pages of the selected page(s)
            typeScope2.IncludeChildren = true;

            workflowScope1.TypeScopes.Add(typeScope1);
            workflowScope1.TypeScopes.Add(typeScope2);

            workflowDefinition.Scopes.Add(workflowScope1);

            workflowManager.SaveChanges();

            return new WorkflowDefinitionProxy(workflowDefinition);
        }

        private IWorkflowExecutionDefinition CreateTwoStepApprovalWorkflowDefinition(Guid definitionId)
        {
            var workflowManager = WorkflowManager.GetManager();
            var backendUsersRole = Config.Get<SecurityConfig>().ApplicationRoles[SecurityConstants.AppRoles.BackendUsers];

            // In 2-level approval the steps are "Approve" and "Publish".
            // In 3-level approval the steps are "Review", "Approve" and "Publish".
            var workflowDefinition = workflowManager.CreateWorkflowDefinition(definitionId);
            workflowDefinition.Title = "2-step workflow for Restricted Users";
            workflowDefinition.WorkflowType = WorkflowType.StandardTwoStep;
            workflowDefinition.AllowAdministratorsToSkipWorkflow = false;
            workflowDefinition.AllowPublishersToSkipWorkflow = false;
            workflowDefinition.AllowNotes = true;
            workflowDefinition.IsActive = true;

            // Levels section
            // Level 1 - Approve
            // Allow everyone in the role "Designers" to approve content.
            var approver1 = Config.Get<SecurityConfig>().ApplicationRoles[SecurityConstants.AppRoles.Designers];

            var approvePermission = workflowManager.CreateWorkflowPermission();
            approvePermission.ActionName = "Approve";
            approvePermission.PrincipalType = WorkflowPrincipalType.Role;
            approvePermission.PrincipalId = approver1.Id.ToString();
            approvePermission.PrincipalName = approver1.Name;

            var level1 = workflowManager.CreateWorkflowLevel();
            level1.ActionName = "Approve";
            level1.Ordinal = 1;
            level1.NotifyAdministrators = true;
            level1.NotifyApprovers = true;
            level1.Permissions.Add(approvePermission);

            workflowDefinition.Levels.Add(level1);

            //Level 2 - Publish          
            var level2 = workflowManager.CreateWorkflowLevel();
            level2.ActionName = "Publish";
            level2.Ordinal = 2;
            level2.NotifyAdministrators = true;
            level2.NotifyApprovers = true;

            // Allow everyone in the role "Editors" to publish content.
            var publisher1 = Config.Get<SecurityConfig>().ApplicationRoles[SecurityConstants.AppRoles.Editors];

            var publishPermission1 = workflowManager.CreateWorkflowPermission();
            publishPermission1.ActionName = "Publish";
            publishPermission1.PrincipalType = WorkflowPrincipalType.Role;
            publishPermission1.PrincipalId = publisher1.Id.ToString();
            publishPermission1.PrincipalName = publisher1.Name;
            level2.Permissions.Add(publishPermission1);

            // Allow user "johnsmith" (if exists) to publish content.
            var publisher2 = UserManager.FindUser("johnsmith");

            // In 2-level approval the second step is "Publish"
            if (publisher2 != null)
            {
                var publishPermission2 = workflowManager.CreateWorkflowPermission();
                publishPermission2.ActionName = "Publish";
                publishPermission2.PrincipalType = WorkflowPrincipalType.User;
                publishPermission2.PrincipalId = publisher2.Id.ToString();
                publishPermission2.PrincipalName = publisher2.UserName.ToString();
                level2.Permissions.Add(publishPermission2);
            }

            workflowDefinition.Levels.Add(level1);

            // Scopes section
            var workflowScope1 = workflowManager.CreateWorkflowScope();
            workflowDefinition.Scopes.Add(workflowScope1);

            workflowManager.SaveChanges();

            return new WorkflowDefinitionProxy(workflowDefinition);
        }
    }
}