using System;
using System.IO;
using System.ComponentModel;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ASPNET.StarterKit.Portal {

    //*********************************************************************
    //
    // PortalModuleControl Class
    //
    // The PortalModuleControl class defines a custom base class inherited by all
    // desktop portal modules within the Portal.
    // 
    // The PortalModuleControl class defines portal specific properties
    // that are used by the portal framework to correctly display portal modules
    //
    //*********************************************************************

    public class PortalModuleControl : UserControl {

        // Private field variables

        private ModuleSettings  _moduleConfiguration;
        private int             _isEditable = 0;
        private int             _portalId = 0;
        private Hashtable       _settings;

        // Public property accessors

        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int ModuleId {

            get {
                return (int) _moduleConfiguration.ModuleId;
            }
        }    

        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int PortalId {

            get {
                return _portalId;
            }
            set {
                _portalId = value;
            }
        }
        
        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool IsEditable {
            
            get {

                // Perform tri-state switch check to avoid having to perform a security
                // role lookup on every property access (instead caching the result)

                if (_isEditable == 0) {
                    
                    // Obtain PortalSettings from Current Context

                    PortalSettings portalSettings = (PortalSettings) HttpContext.Current.Items["PortalSettings"];

                    if (portalSettings.AlwaysShowEditButton == true || PortalSecurity.IsInRoles(_moduleConfiguration.AuthorizedEditRoles)) {
                        _isEditable = 1;
                    }
                    else {
                        _isEditable = 2;
                    }
                }

                return (_isEditable == 1);
            }
        }

        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ModuleSettings ModuleConfiguration {

            get {
                return _moduleConfiguration;
            }
            set {
                _moduleConfiguration = value;
            }
        }

        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Hashtable Settings {

            get {

                if (_settings == null) {

                    _settings = Configuration.GetModuleSettings(ModuleId);
                }

                return _settings;
            }
         }
    }
    
    //*********************************************************************
    //
    // CachedPortalModuleControl Class
    //
    // The CachedPortalModuleControl class is a custom server control that
    // the Portal framework uses to optionally enable output caching of 
    // individual portal module's content.
    //
    // If a CacheTime value greater than 0 seconds is specified within the 
    // ASPNET.StarterKit.Portal.Config configuration file, then the CachePortalModuleControl
    // will automatically capture the output of the Portal Module User Control
    // it wraps.  It will then store this captured output within the ASP.NET
    // Cache API.  On subsequent requests (either by the same browser -- or
    // by other browsers visiting the same portal page), the CachedPortalModuleControl
    // will attempt to resolve the cached output out of the cache.
    //
    // Note: In the event that previously cached output can't be found in the
    // ASP.NET Cache, the CachedPortalModuleControl will automatically instatiate
    // the appropriate portal module user control and place it within the
    // portal page.
    //
    //*********************************************************************

    public class CachedPortalModuleControl : Control {

        // Private field variables

        private ModuleSettings  _moduleConfiguration;
        private String          _cachedOutput = "";
        private int             _portalId = 0;


        // Public property accessors

        public ModuleSettings ModuleConfiguration {

            get {
                return _moduleConfiguration;
            }
            set {
                _moduleConfiguration = value;
            }
        }

        public int ModuleId {

            get {
                return _moduleConfiguration.ModuleId;
            }
        }

        public int PortalId {

            get {
                return _portalId;
            }
            set {
                _portalId = value;
            }
        }

        //*********************************************************************
        //
        // CacheKey Property
        //
        // The CacheKey property is used to calculate a "unique" cache key
        // entry to be used to store/retrieve the portal module's content
        // from the ASP.NET Cache.
        //
        //*********************************************************************

        public String CacheKey {

            get {
                return "Key:" + this.GetType().ToString() + this.ModuleId + PortalSecurity.IsInRoles(_moduleConfiguration.AuthorizedEditRoles);
            }
        }

        //*********************************************************************
        //
        // CreateChildControls Method
        //
        // The CreateChildControls method is called when the ASP.NET Page Framework
        // determines that it is time to instantiate a server control.
        // 
        // The CachedPortalModuleControl control overrides this method and attempts
        // to resolve any previously cached output of the portal module from the 
        // ASP.NET cache.  
        //
        // If it doesn't find cached output from a previous request, then the
        // CachedPortalModuleControl will instantiate and add the portal module's
        // User Control instance into the page tree.
        //
        //*********************************************************************

        protected override void CreateChildControls() {

            // Attempt to resolve previously cached content from the ASP.NET Cache

            if (_moduleConfiguration.CacheTime > 0) {
                _cachedOutput = (String) Context.Cache[CacheKey];
            }

            // If no cached content is found, then instantiate and add the portal
            // module user control into the portal's page server control tree

            if (_cachedOutput == null) {

                base.CreateChildControls();

                PortalModuleControl module = (PortalModuleControl) Page.LoadControl(_moduleConfiguration.DesktopSrc);
                
                module.ModuleConfiguration = this.ModuleConfiguration;
                module.PortalId = this.PortalId;

                this.Controls.Add(module);
            }
        }

        //*********************************************************************
        //
        // Render Method
        //
        // The Render method is called when the ASP.NET Page Framework
        // determines that it is time to render content into the page output stream.
        // 
        // The CachedPortalModuleControl control overrides this method and captures
        // the output generated by the portal module user control.  It then 
        // adds this content into the ASP.NET Cache for future requests.
        //
        //*********************************************************************

        protected override void Render(HtmlTextWriter output) {

            // If no caching is specified, render the child tree and return 

            if (_moduleConfiguration.CacheTime == 0) {
                base.Render(output);
                return;
            }

            // If no cached output was found from a previous request, render
            // child controls into a TextWriter, and then cache the results
            // in the ASP.NET Cache for future requests.

            if (_cachedOutput == null) {

                TextWriter tempWriter = new StringWriter();
                base.Render(new HtmlTextWriter(tempWriter));
                _cachedOutput = tempWriter.ToString();

                Context.Cache.Insert(CacheKey, _cachedOutput, null, DateTime.Now.AddSeconds(_moduleConfiguration.CacheTime), TimeSpan.Zero);
            }

            // Output the user control's content

            output.Write(_cachedOutput);
        }
    }
}
