﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Reflection;
using System.IO;
using System.Windows.Resources;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Markup;
using System.Xml;
using System.Text;

namespace CS.SL.Common.Helper
{
    public class ResourceHelper
    {
        #region Get Resource
        /// <summary>
        /// After we have the xaml string, we can create an instance of the class and insert the object into our main document using XamlReader.Load. For example,
        /// _asteroids[i].PathObject = XamlReader.Load(thisXaml, false) as Path;
        /// </summary>
        /// <param name="resourceName"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string GetResource(Type type, string resourceName)
        {
            return GetResource(type.Assembly,resourceName);
        }
        public static Stream GetResourceStream(Type type,string resourceName )
        {
            return GetResourceStream(type.Assembly, resourceName);
        }

        public static string GetResource(string resourceName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            return GetResource(assembly, resourceName);
        }

        public static Stream GetResourceStream(string resourceName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            return GetResourceStream(assembly, resourceName);
        }
        public static string GetResource(Assembly ass, string resourceName)
        {
            return ReadStream(GetResourceStream(ass, resourceName));
        }
        public static Stream GetResourceStream(Assembly ass, string resourceName)
        {
            return ass.GetManifestResourceStream(resourceName);
        }
        #endregion

        #region XAP Read

        public static string GetResourceFromXAP(Stream package, string contentType, string resourcePath)
        {
            return ReadStream(GetResourceStreamFromXAP(package, contentType, resourcePath));
        }
        /// <summary>
        ///     Get Resource Stream From XAP
        /// </summary>
        /// <param name="package">stream of XAP</param>
        /// <param name="resourcePath">Relative resource path</param>
        /// <returns></returns>
        public static Stream GetResourceStreamFromXAP(Stream stream, string contentType, string resourcePath)
        {
            return Application.GetResourceStream(new StreamResourceInfo(stream, contentType), new Uri(resourcePath, UriKind.Relative)).Stream;
        }
        /// <summary>
        /// Load specfic assembly from XAP package stream
        /// </summary>
        /// <param name="package"></param>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        public static Assembly LoadAssemblyFromXap(Stream package, string assemblyName)
        {
            AssemblyPart part = new AssemblyPart();
            Assembly asm = part.Load(GetResourceStreamFromXAP(package, "application/binary", assemblyName));
            return asm;
        }
        /// <summary>
        /// Create and load specfic assembly from XAP package stream
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="package"></param>
        /// <param name="assemblyName"></param>
        /// <param name="typeName"></param>
        /// <returns></returns>
        public static T GetObject<T>(Stream package, string assemblyName, string typeName)
        {
            Assembly asm = LoadAssemblyFromXap(package, assemblyName);
            return (T)asm.CreateInstance(typeName);
        }

        /// <summary>
        /// Create From XAP
        /// </summary>
        /// <param name="package">stream of package</param>
        /// <param name="rootVisualClassName">
        ///     root class name
        /// </param>
        /// <returns></returns>
        public static Object CreateFromXAP(Stream package, string rootVisualClassName)
        {
            string appManifestString = GetResourceFromXAP(package, null, "AppManifest.xaml");
            Stream appManifestStream = new MemoryStream(Encoding.UTF8.GetBytes(appManifestString));
            Assembly mainAssembly = null;
            using (XmlReader reader = XmlReader.Create(appManifestStream))
            {
                reader.MoveToContent();
                string entryPointAssembly = reader.GetAttribute("EntryPointAssembly");
                string entryPointType = reader.GetAttribute("EntryPointType");
                string runtimeVersion = reader.GetAttribute("RuntimeVersion");
                while (reader.Read())
                {
                    if (reader.Name.Equals("AssemblyPart"))
                    {
                        string source = reader.GetAttribute("Source");
                        string name = reader.GetAttribute("Name");
                        Assembly asm = LoadAssemblyFromXap(package, source);
                        if (source.StartsWith(rootVisualClassName == null ? entryPointAssembly : rootVisualClassName.Split('.')[0]))
                        {
                            mainAssembly = asm;
                        }
                    }
                }
                Type asmType = mainAssembly.GetType(rootVisualClassName == null ? entryPointType : rootVisualClassName);
                return Activator.CreateInstance(asmType);
            }
        }
        public static Application CreateFromXAP(Stream package)
        {
            return CreateFromXAP(package, null) as Application;
        }


        #endregion

        public static string ReadStream(Stream str)
        {
            using (System.IO.StreamReader reader = new System.IO.StreamReader(str))
            {
                return reader.ReadToEnd();
            }
        }

    }
}
