/// Game Resource browser
//
// Copyright (C) 2014-2015 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//

using System;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Documents;
using GARbro.GUI.Properties;
using GARbro.GUI.Strings;

namespace GARbro.GUI
{
    /// <summary>
    /// Interaction logic for AboutBox.xaml
    /// </summary>
    public partial class AboutBox : Rnd.Windows.ModalWindow
    {
        public AboutBox()
        {
            InitializeComponent();
            LicenseTabText.Document = GetResourceDoc ("GARbro.GUI.LICENSE");
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        #region License text backend

        static FlowDocument GetResourceDoc (string resource)
        {
            var assembly = Assembly.GetExecutingAssembly();
            using (var stream = assembly.GetManifestResourceStream (resource))
            {
                if (null == stream)
                    return new FlowDocument();
                return ReadPlainText (stream);
            }
        }

        /// <summary>
        /// Read plain text from stream and return it as FlowDocument.
        /// </summary>
        static FlowDocument ReadPlainText (Stream stream)
        {
            using (var reader = new StreamReader (stream))
            {
                var doc = new FlowDocument();
                var para = new Paragraph();
                for (;;)
                {
                    var line = reader.ReadLine();
                    if (null == line)
                        break;
                    if (line.Length > 0)
                    {
                        if (para.Inlines.Count > 0)
                            para.Inlines.Add (" ");
                        para.Inlines.Add (line);
                    }
                    else
                    {
                        if (0 == para.Inlines.Count)
                            para.Inlines.Add (new LineBreak());
                        doc.Blocks.Add (para);
                        para = new Paragraph();
                    }
                }
                if (para.Inlines.Count > 0)
                    doc.Blocks.Add (para);
                return doc;
            }
        }

        #endregion

        #region Assembly Attribute Accessors

        public string AssemblyTitle
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
                if (attributes.Length > 0)
                {
                    AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
                    if (titleAttribute.Title != "")
                    {
                        return titleAttribute.Title;
                    }
                }
                return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
            }
        }

        public string VersionString
        {
            get
            {
                return string.Format (guiStrings.MsgVersion, AssemblyVersion);
            }
        }

        public string AssemblyVersion
        {
            get
            {
                return Assembly.GetExecutingAssembly().GetName().Version.ToString();
            }
        }

        public string AssemblyDescription
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyDescriptionAttribute)attributes[0]).Description;
            }
        }

        public string AssemblyProduct
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyProductAttribute)attributes[0]).Product;
            }
        }

        public string AssemblyCopyright
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
            }
        }

        public string AssemblyCompany
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyCompanyAttribute)attributes[0]).Company;
            }
        }
        #endregion
    }

    public class BooleanToVisibiltyConverter : IValueConverter
    {
        /// <summary>Convert a boolean value to a Visibility value</summary>
        public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool isVisible = (bool)value;

            // If visibility is inverted by the converter parameter, then invert our value
            if (IsVisibilityInverted (parameter))
                isVisible = !isVisible;

            return (isVisible ? Visibility.Visible : Visibility.Collapsed);
        }

        /// <summary>
        /// Determine the visibility mode based on a converter parameter.  This parameter is
        /// of type Visibility, and specifies what visibility value to return when the boolean
        /// value is true.
        /// </summary>
        private static Visibility GetVisibilityMode(object parameter)
        {
            // Default to Visible
            Visibility mode = Visibility.Visible;

            // If a parameter is specified, then we'll try to understand it as a Visibility value
            if (parameter != null)
            {
                // If it's already a Visibility value, then just use it
                if (parameter is Visibility)
                {
                    mode = (Visibility)parameter;
                }
                else
                {
                    // Let's try to parse the parameter as a Visibility value, throwing an exception when the parsing fails
                    try
                    {
                        mode = (Visibility)Enum.Parse(typeof(Visibility), parameter.ToString(), true);
                    }
                    catch (FormatException e)
                    {
                        throw new FormatException("Invalid Visibility specified as the ConverterParameter.  Use Visible or Collapsed.", e);
                    }
                }
            }
        
            // Return the detected mode
            return mode;
        }
        
        /// <summary>
        /// Determine whether or not visibility is inverted based on a converter parameter.
        /// When the parameter is specified as Collapsed, that means that when the boolean value
        /// is true, we should return Collapsed, which is inverted.
        /// </summary>
        private static bool IsVisibilityInverted(object parameter)
        {
            return (GetVisibilityMode(parameter) == Visibility.Collapsed);
        }

        /// <summary>
        /// Support 2-way databinding of the VisibilityConverter, converting Visibility to a boolean
        /// </summary>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            bool isVisible = ((Visibility)value == Visibility.Visible);
        
            // If visibility is inverted by the converter parameter, then invert our value
            if (IsVisibilityInverted(parameter))
                isVisible = !isVisible;
        
            return isVisible;
        }
    }

    [ValueConversion(typeof(bool), typeof(string))]
    class CanCreateConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (bool)value ? "[r/w]" : "[r]";
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return false;
        }
    }
}