#region Copyright (C) 2007-2012 Team MediaPortal

/*
    Copyright (C) 2007-2011 Team MediaPortal
    http://www.team-mediaportal.com

    This file is part of MediaPortal 2

    MediaPortal 2 is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MediaPortal 2 is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MediaPortal 2.  If not, see <http://www.gnu.org/licenses/>.
*/

#endregion


using System;
using System.Collections.Generic;

using MediaPortal.Common;
using MediaPortal.Common.Commands;
using MediaPortal.Common.General;
using MediaPortal.Common.Logging;
using MediaPortal.Common.Messaging;
using MediaPortal.Common.Settings;
using MediaPortal.Common.Localization;
using MediaPortal.UI.Presentation.Models;
using MediaPortal.UI.Presentation.DataObjects;
using MediaPortal.UI.Presentation.Workflow;

using MediaPortal.Plugins.SlimTvClient.Interfaces;
using MediaPortal.Plugins.SlimTvClient;



using  MediaPortal.Plugins.MyTestPlugin.Settings; //needed for configuration setting loading

namespace MyTestPlugin.Models
{
  /// <summary>
  /// Example for a simple model.
  /// </summary>
  /// <remarks>
  /// <para>
  /// Models are used for providing data from the system to the skin and for executing actions (commands)
  /// which are triggered by the Skin, for example by clicking a button.
  /// </para>
  /// <para>
  /// All public properties can be data-bound by the skin, for example the <see cref="HelloString"/> property.
  /// Note that properties, which are updated by the model and whose new value should be propagated to the
  /// skin, must be backed by an instance of <see cref="AbstractProperty"/>. That instance must be made available
  /// to the skin engine by publishing it under the same name as the actual property plus "Property", see for example
  /// <see cref="HelloStringProperty"/>. In models, always <see cref="WProperty"/> instances are used.
  /// </para>
  /// <para>
  /// You can also consider to implement the interface <see cref="IWorkflowModel"/>, which makes it
  /// possible to attend the screenflow = workflow of the user session. When that interface is implemented and this
  /// model is registered in a workflow state as backing workflow model, the model will get notifications when the
  /// GUI navigation switches to or away from its workflow state.
  /// </para>
  /// <para>
  /// To make an UI model known by the system (and thus loadable by the skin), it is necessary to register it
  /// in the <c>plugin.xml</c> file.
  /// </para>
  /// </remarks>
  /// 
    


    public class MyTestPluginScreen2 : IWorkflowModel, IDisposable
    {


        


        #region Constants

        //must be model ID defined in workflow and plugin.xml
        public const string MYTESTPLUGINSCREEN2_MODEL_ID_STR = "cefc2f41-8a0d-4f92-b2e7-c7fa2194e90d";
        public readonly static Guid MYTESTPLUGINSCREEN2_MODEL_ID = new Guid(MYTESTPLUGINSCREEN2_MODEL_ID_STR);


        /// <summary>
        /// This is a localized string resource. Localized string resources always look like this:
        /// <example>
        /// [Section.Name]
        /// </example>
        /// Localized resources must be present at least in the english language, as this is the default.
        /// In the english language file of this hello world plugin, you'll find the translation of this string.
        /// The language file is located at: /Language/strings_en.xml
        /// </summary>
        

        
        protected const string SELECTED_ITEM_RESOURCE = "[MyTestPluginScreen2.SelectedItem]";
        protected const string FOCUSED_ITEM_RESOURCE = "[MyTestPluginScreen2.FocusedItem]";
        protected const string ITEM_RESOURCE = "[MyTestPluginScreen2.Item]";
        

        #endregion

        #region Global Variables

        
        //Logger
        ILogger mylogger = ServiceRegistration.Get<ILogger>();


        

        #endregion Global Variables
         

        #region Properties for skins

        /// <summary>
        /// This property holds a string that we will modify in this tutorial.
        /// </summary>
        protected readonly AbstractProperty _selectedItemProperty;
        protected readonly AbstractProperty _focusedItemProperty;

        

        // Itemlist that is exposed to the skin (ListView in skin)
        private ItemsList _testlist = null;
        //protected readonly AbstractProperty _testlistProperty;

        /// <summary>
        /// This sample property will be accessed by the hello_world screen. Note that the data type must be the same
        /// as given in the instantiation of our backing property <see cref="_helloStringProperty"/>.
        /// </summary>
        
        
        public string SelectedItem
        {
            get { return (string)_selectedItemProperty.GetValue(); }
            set { _selectedItemProperty.SetValue(value); }
        }

        public string FocusedItem
        {
            get { return (string)_focusedItemProperty.GetValue(); }
            set { _focusedItemProperty.SetValue(value); }
        }

        public ItemsList MyListViewItems
        {
            get { return _testlist; }
        }

        /// <summary>
        /// This is the dependency property for our sample string. It is needed to propagate changes to the skin.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the screen databinds to the <see cref="HelloString"/> property in a binding mode which will propagate data
        /// changes from the model to the skin (OneWay, TwoWay), the SkinEngine will attach a change handler to this property
        /// and react to changes.
        /// </para>
        /// <para>
        /// In other words: For each property <c>Xyz</c>, which should be able to be attached to, there must be an
        /// <see cref="AbstractProperty"/> with name <c>XyzProperty</c>.
        /// Only if <c>XyzProperty</c> is present in the model, value changes can be propagated to the skin.
        /// </para>
        /// </remarks>
        
        public AbstractProperty SelectedItemProperty
        {
            get { return _selectedItemProperty; }
        }

        public AbstractProperty FocusedItemProperty
        {
            get { return _focusedItemProperty; }
        }

        /*
        public AbstractProperty MyListViewItemsProperty
        {
            get { return _testlistProperty; }
        }*/

        //do not forget Wproperties in constructor!
        #endregion Properties for skins





        #region constructor
        /// <summary>
        /// Constructor... this one is called by the WorkflowManager when this model is loaded due to a screen reference.
        /// </summary>
        public MyTestPluginScreen2()  //will be called when the screen is the first time loaded not the same as Init() !!!
        {

            mylogger.Debug("MyTestPluginScreen2:MyTestPluginScreen2(): Constructor called");

            
            // In models, properties will always be WProperty instances. When using SProperties for screen databinding,
            // the system might run into memory leaks.
            _selectedItemProperty = new WProperty(typeof(string), SELECTED_ITEM_RESOURCE);
            _focusedItemProperty = new WProperty(typeof(string), FOCUSED_ITEM_RESOURCE);
            //_testlistProperty = new WProperty(typeof(ItemsList), FOCUSED_ITEM_RESOURCE);
            
        }
       
        #endregion constructor



        #region public methods
        public void InitListItems()
        {
            //load settings 
            MyTestPluginSettings settings = ServiceRegistration.Get<ISettingsManager>().Load<MyTestPluginSettings>();

            //define all items for ListView in skin and use MySetting_Int for number of items to create
            _testlist = new ItemsList();
            for (int i = 0; i < settings.MySetting_Int; i++)
            {
                ListItem myitem = new ListItem();
                string myitemstring = LocalizationHelper.Translate(ITEM_RESOURCE, i);
                //Name is the default item style! If you use any other key you must define a style in the skin!
                myitem.SetLabel("Name",myitemstring);
                myitem.Selected = myitem;
                mylogger.Debug("Adding Name="+myitemstring);
                //this command will be executed after selection
                myitem.Command = new MethodDelegateCommand(() => SelectedItemChanged(myitem));
                
                _testlist.Add(myitem);

                
            }

            //update skin
            mylogger.Debug(" InitListItems(): FireChange");
            MyListViewItems.FireChange();
            mylogger.Debug(" InitListItems(): Completed");
        }


        public void FocusedItemChanged(ListItem focusedListItem)
        {
            if (focusedListItem == null)
                return;

            mylogger.Debug("FocusedItemChanged: Focused item=" + focusedListItem.Labels["Name"]);

            //update label
            FocusedItem = LocalizationHelper.Translate(FOCUSED_ITEM_RESOURCE, focusedListItem.Labels["Name"]);
            mylogger.Debug("FocusedItemChanged: Completed");
        }

       

        public void SelectedItemChanged(ListItem selectedListItem)
        {
            if (selectedListItem == null)
                return;

            mylogger.Debug("SelectedItemChanged: Selected item number=" + selectedListItem.Labels["Name"]);
            string selectedItemstring = selectedListItem.Labels["Name"].ToString();
            mylogger.Debug("SelectedItemChanged: Selected item=" + selectedItemstring);

            //update label
            SelectedItem = LocalizationHelper.Translate(SELECTED_ITEM_RESOURCE, selectedListItem.Labels["Name"].ToString());
            mylogger.Debug("SelectedItemChanged: Completed");
        }





        #endregion public methods


        #region IWorkflowModel implementation
        // to use this you must have derived the class from IWorkflowModel, IDisposable
        // and you must have defined in plugin.xml a workflowstate
        // WorkflowModel="023c44f2-3329-4781-9b4a-c974444c0b0d"/> <!-- MyTestPlugin Model -->

        public Guid ModelId
        {
            get { return MYTESTPLUGINSCREEN2_MODEL_ID; }
        }

        public bool CanEnterState(NavigationContext oldContext, NavigationContext newContext)
        {
            mylogger.Debug("MyTestPluginScreen2:CanEnterState: oldContext.WorkflowModelId =" + oldContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:CanEnterState: oldContext.WorkflowState =" + oldContext.WorkflowState);
            mylogger.Debug("MyTestPluginScreen2:CanEnterState: newContext.WorkflowModelId =" + newContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:CanEnterState: newContext.WorkflowState =" + newContext.WorkflowState);
            mylogger.Debug("");
            return true;
        }

        public void EnterModelContext(NavigationContext oldContext, NavigationContext newContext)
        {
            mylogger.Debug("MyTestPluginScreen2:EnterModelContext: oldContext.WorkflowModelId =" + oldContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:EnterModelContext: oldContext.WorkflowState =" + oldContext.WorkflowState);
            mylogger.Debug("MyTestPluginScreen2:EnterModelContext: newContext.WorkflowModelId =" + newContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:EnterModelContext: newContext.WorkflowState =" + newContext.WorkflowState);
            mylogger.Debug("");
            OnPageLoad(oldContext);
        }

        public void ExitModelContext(NavigationContext oldContext, NavigationContext newContext)
        {
            mylogger.Debug("MyTestPluginScreen2:ExitModelContext: oldContext.WorkflowModelId =" + oldContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:ExitModelContext: oldContext.WorkflowState =" + oldContext.WorkflowState);
            mylogger.Debug("MyTestPluginScreen2:ExitModelContext: newContext.WorkflowModelId =" + newContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:ExitModelContext: newContext.WorkflowState =" + newContext.WorkflowState);
            mylogger.Debug("");
            OnPageDestroy(newContext);
        }

        public void ChangeModelContext(NavigationContext oldContext, NavigationContext newContext, bool push)
        {

            mylogger.Debug("MyTestPluginScreen2:ChangeModelContext: oldContext.WorkflowModelId =" + oldContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:ChangeModelContext: oldContext.WorkflowState =" + oldContext.WorkflowState);
            mylogger.Debug("MyTestPluginScreen2:ChangeModelContext: newContext.WorkflowModelId =" + newContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:ChangeModelContext: newContext.WorkflowState =" + newContext.WorkflowState);
            mylogger.Debug("");
        }

        public void Deactivate(NavigationContext oldContext, NavigationContext newContext)
        {

            mylogger.Debug("MyTestPluginScreen2:Deactivate: oldContext.WorkflowModelId =" + oldContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:Deactivate: oldContext.WorkflowState =" + oldContext.WorkflowState);
            mylogger.Debug("MyTestPluginScreen2:Deactivate: newContext.WorkflowModelId =" + newContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:Deactivate: newContext.WorkflowState =" + newContext.WorkflowState);
            mylogger.Debug("");
            OnPageDestroy(newContext);
        }

        public void Reactivate(NavigationContext oldContext, NavigationContext newContext)
        {

            mylogger.Debug("MyTestPluginScreen2:Reactivate: oldContext.WorkflowModelId =" + oldContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:Reactivate: oldContext.WorkflowState =" + oldContext.WorkflowState);
            mylogger.Debug("MyTestPluginScreen2:Reactivate: newContext.WorkflowModelId =" + newContext.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:Reactivate: newContext.WorkflowState =" + newContext.WorkflowState);
            mylogger.Debug("");
            OnPageLoad(oldContext);
        }

        public void UpdateMenuActions(NavigationContext context, IDictionary<Guid, WorkflowAction> actions)
        {


            mylogger.Debug("MyTestPluginScreen2:UpdateMenuActions: context.WorkflowModelId =" + context.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:UpdateMenuActions: context.WorkflowState =" + context.WorkflowState);
            mylogger.Debug("");
        }

        public ScreenUpdateMode UpdateScreen(NavigationContext context, ref string screen)
        {

            mylogger.Debug("MyTestPluginScreen2:UpdateScreen: context.WorkflowModelId =" + context.WorkflowModelId);
            mylogger.Debug("MyTestPluginScreen2:UpdateScreen: context.WorkflowState =" + context.WorkflowState);
            mylogger.Debug("MyTestPluginScreen2:UpdateScreen: screen =" + screen);
            mylogger.Debug("");
            return ScreenUpdateMode.AutoWorkflowManager;
        }

        public void Dispose()
        {

            //seems to be usable for MP1 function DeInit()
            mylogger.Debug("MyTestPluginScreen2:Dispose() - disposing");

            
        }


        public void OnPageLoad(NavigationContext oldContext)
        {
            //always called when plugin screeen is shown
            mylogger.Debug("MyTestPluginScreen2:OnPageLoad()");

            //show listitems
            InitListItems();

            
        }

        public void OnPageDestroy(NavigationContext newContext)
        {
            //always called when plugin screeen is left
            // but .. not called when client is exited during screen!
            mylogger.Debug("MyTestPluginScreen2:OnPageDestroy()");

            _testlist.Clear();
            _testlist = null;
        }
        #endregion





    }
    

    
    

    
}
