using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ynhtm.Common
{
    public static class Utils
    {
        public static void RegisterClientScriptVar(this ClientScriptManager script, Type type, string key, string name, object obj)
        {
            if (name.IsNullOrWhiteSpace()) throw new ArgumentNullException("name");
            script.RegisterClientScriptBlock(type, key, "var " + name + " = " + new JavaScriptSerializer().Serialize(obj) + ";\r\n", true);
        }

        static string ClientScriptCall(string methodName, bool isTry, params object[] args)
        {
            if (methodName.IsNullOrWhiteSpace()) throw new ArgumentNullException("methodName");
            var arg = "";
            var js = new JavaScriptSerializer();
            if (args != null)
            {
                foreach (object i in args)
                {
                    if (arg != "") arg += ",";
                    arg += js.Serialize(i);
                }
            }
            if (isTry) return "try { " + methodName + "(" + arg + "); } catch(e) { }\r\n";
            return methodName + "(" + arg + ");\r\n";
        }

        public static void RegisterClientScriptBlockCall(this ClientScriptManager script, Type type, string key, string methodName, params object[] args)
        {
            script.RegisterClientScriptBlock(type, key, ClientScriptCall(methodName, false, args), true);
        }

        public static void TryRegisterClientScriptBlockCall(this ClientScriptManager script, Type type, string key, string methodName, params object[] args)
        {
            script.RegisterClientScriptBlock(type, key, ClientScriptCall(methodName, true, args), true);
        }

        public static void RegisterClientScriptBlockCall(this ClientScriptManager script, Type type, string key, string methodName)
        {
            script.RegisterClientScriptBlockCall(type, key, methodName, null);
        }

        public static void TryRegisterClientScriptBlockCall(this ClientScriptManager script, Type type, string key, string methodName)
        {
            script.TryRegisterClientScriptBlockCall(type, key, methodName, null);
        }

        public static void RegisterStartupScriptCall(this ClientScriptManager script, Type type, string key, string methodName, params object[] args)
        {
            script.RegisterStartupScript(type, key, ClientScriptCall(methodName, false, args), true);
        }

        public static void TryRegisterStartupScriptCall(this ClientScriptManager script, Type type, string key, string methodName, params object[] args)
        {
            script.RegisterStartupScript(type, key, ClientScriptCall(methodName, true, args), true);
        }

        public static void RegisterStartupScriptCall(this ClientScriptManager script, Type type, string key, string methodName)
        {
            script.RegisterStartupScriptCall(type, key, methodName, null);
        }

        public static void TryRegisterStartupScriptCall(this ClientScriptManager script, Type type, string key, string methodName)
        {
            script.TryRegisterStartupScriptCall(type, key, methodName, null);
        }

        static T EvalConvertTo<T>(object obj)
        {
            if (obj == null || DBNull.Value.Equals(obj)) return default(T);
            return (T)Convert.ChangeType(obj, typeof(T));
        }

        public static T Eval<T>(this TemplateControl control, string expression)
        {
            return EvalConvertTo<T>(DataBinder.Eval(control.Page.GetDataItem(), expression));
        }

        public static ListItem SelectValue(this ListControl list, string value, StringComparer comparer, bool selected = true)
        {
            var item = list.Items.FindByValue(value, comparer);
            if (item != null)
            {
                list.SelectedIndex = -1;
                item.Selected = selected;
            }
            return item;
        }

        public static ListItem SelectValue(this ListControl list, string value, bool selected = true)
        {
            return list.SelectValue(value, StringComparer.OrdinalIgnoreCase, selected);
        }

        public static ListItem SelectText(this ListControl list, string text, StringComparer comparer, bool selected = true)
        {
            var item = list.Items.FindByText(text, comparer);
            if (item != null)
            {
                list.SelectedIndex = -1;
                item.Selected = selected;
            }
            return item;
        }

        public static ListItem SelectText(this ListControl list, string text, bool selected = true)
        {
            return list.SelectText(text, StringComparer.OrdinalIgnoreCase, selected);
        }

        public static ListItem FindByValue(this ListItemCollection items, string value, StringComparer comparer)
        {
            foreach (ListItem i in items)
            {
                if (string.Equals(i.Value, value)) return i;
            }
            return null;
        }

        public static ListItem FindByText(this ListItemCollection items, string text, StringComparer comparer)
        {
            foreach (ListItem i in items)
            {
                if (string.Equals(i.Text, text)) return i;
            }
            return null;
        }

        public static T Get<T>(string s, Converter<string, T> converter, T defaultValue = default(T))
        {
            try { return converter.Invoke(s); }
            catch { return defaultValue; }
        }

        public static T Get<T>(this ITextControl control, Converter<string, T> converter, T defaultValue = default(T))
        {
            return Get(control.Text, converter, defaultValue);
        }

        public static T? TryGet<T>(string s, Converter<string, T> converter, T? defaultValue = null) where T : struct
        {
            try { return converter.Invoke(s); }
            catch { return defaultValue; }
        }

        public static T? TryGet<T>(this ITextControl control, Converter<string, T> converter, T? defaultValue = null) where T : struct
        {
            return TryGet(control.Text, converter, defaultValue);
        }

        public static void ShowInfo(this Page page, string s)
        {
            page.ClientScript.RegisterClientScriptBlockCall(page.GetType(), "ShowInfo", "$.Msg.info", s);
        }

        public static void ShowError(this Page page, string s)
        {
            page.ClientScript.RegisterClientScriptBlockCall(page.GetType(), "ShowError", "$.Msg.error", s);
        }

        public static void ShowAlert(this Page page, string s)
        {
            page.ClientScript.RegisterClientScriptBlockCall(page.GetType(), "ShowAlert", "$.Msg.alert", s);
        }

        public static string PathEncode(string path)
        {
            path = Regex.Replace(path, @"\\", "/", RegexOptions.Compiled);
            path = Regex.Replace(path, @"/+", "/", RegexOptions.Compiled);
            path = Regex.Replace(path, @"(^/+)|(/+$)", "", RegexOptions.Compiled);
            return path;
        }

        public static string GetFileSize(long length)
        {
            if (1073741824 <= length) return (length / 1073741824F).ToString("0.##") + " GB";
            if (1048576 <= length) return (length / 1048576F).ToString("0.##") + " MB";
            if (1024 <= length) return (length / 1024F).ToString("0.##") + " KB";
            return length + " 字节";
        }

        public static string Thumb(string url, int width, int height, ImageThumbMode mode = ImageThumbMode.Auto, long quality = 80)
        {
            return "/API/Thumb.ashx?Size=" + width + "%2c" + height + "&Url=" + url.UrlEncode() + "&Mode=" + (int)mode + "&Quality=" + quality;
        }

        public static string Combine(params string[] paths)
        {
            return Path.Combine(paths);
        }
    }
}