using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class landing_api_reset_password : System.Web.UI.Page
{
    System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();

    protected void Page_Load(object sender, EventArgs e)
    {
        string action = (string.IsNullOrEmpty(Request.Form["action"])) ? String.Empty : Request.Form["action"];
        action = action.ToUpper(); 

        switch (action)
        {
            case "SETTOKEN":
                SetToken(); 
                break; 
            case "RESETWITHTOKEN":
                break; 
            default:
                Response.Write(jss.Serialize(new { status = "INVALIDACTION" }));
                break; 
        }
    }

    private void SetToken()
    {
        string username = (String.IsNullOrEmpty(Request.Form["username"])) ? null : Request.Form["username"];
        string email = (String.IsNullOrEmpty(Request.Form["email"])) ? null : Request.Form["email"];

        if (username != null || email != null)
        {
            int? userid = DAL.getUserId(username, email);
            if (userid != null)
            {
                string token = RandomString(45);
                string status = DAL.setResetPasswordToken((int)userid, token);

                if (status == "OK")
                {
                    Dictionary<string, string> userinfo = DAL.getUserInfo((int)userid);
                    if (userinfo != null)
                    {
                        string userEmail = userinfo["Email"];
                        bool sendingEmail = SendResetPasswordEmail(userEmail, token);
                        if (sendingEmail == true)
                        {
                            Response.Write(jss.Serialize(new { status = "OK" }));
                        }
                        else
                        {
                            Response.Write(jss.Serialize(new { status = "FAILEDWHENSENDINGEMAIL" }));
                        }
                    }
                }
                else
                {
                    Response.Write(jss.Serialize(new { status = "FAILEDWHENSETTINGTOKEN" }));
                }
            }
            else
            {
                Response.Write(jss.Serialize(new { status = "INVALIDUSER" }));
            }
        }
        else
        {
            Response.Write(jss.Serialize(new { status = "MISSINGPARAMETERS" }));
        }
    }

    private bool SendResetPasswordEmail(string email, string token)
    {
        string siteLang = "EN";
        HttpCookie lang = Request.Cookies["siteLanguage"];
        siteLang = (lang != null) ? lang.Value : siteLang;

        string resx = AppDomain.CurrentDomain.BaseDirectory + "\\landing\\api\\App_LocalResources\\resources" + ((siteLang == "EN") ? "" : "." + siteLang) + ".resx";
        System.Resources.ResXResourceReader rsxr = new System.Resources.ResXResourceReader(resx);
        Dictionary<string, string> resourceMap = new Dictionary<string, string>();
        foreach (DictionaryEntry d in rsxr)
            resourceMap.Add(d.Key.ToString(), d.Value.ToString());

        rsxr.Close();

        string templateURL = string.Format("{0}?token={1}", "http://" + Request.Url.Host + Request.ApplicationPath + "/landing/email-templates/reset-password.aspx", token);
        string messageBody = Mail.GetEmailTemplate(templateURL, Request.Url.ToString(), Request.Cookies["siteLanguage"]);

        bool result = false;
        result = Mail.SendEmail(email, resourceMap["reset_password_email_subject"], messageBody);

        return result; 
    }

    public static string RandomString(int length, string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") {
        if (length < 0) throw new ArgumentOutOfRangeException("length", "length cannot be less than zero.");
        if (string.IsNullOrEmpty(allowedChars)) throw new ArgumentException("allowedChars may not be empty.");

        const int byteSize = 0x100;
        var allowedCharSet = new HashSet<char>(allowedChars).ToArray();
        if (byteSize < allowedCharSet.Length) throw new ArgumentException(String.Format("allowedChars may contain no more than {0} characters.", byteSize));

        // Guid.NewGuid and System.Random are not particularly random. By using a
        // cryptographically-secure random number generator, the caller is always
        // protected, regardless of use.
        using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider())
        {
            var result = new StringBuilder();
            var buf = new byte[128];
            while (result.Length < length)
            {
                rng.GetBytes(buf);
                for (var i = 0; i < buf.Length && result.Length < length; ++i)
                {
                    // Divide the byte into allowedCharSet-sized groups. If the
                    // random value falls into the last group and the last group is
                    // too small to choose from the entire allowedCharSet, ignore
                    // the value in order to avoid biasing the result.
                    var outOfRangeStart = byteSize - (byteSize % allowedCharSet.Length);
                    if (outOfRangeStart <= buf[i]) continue;
                    result.Append(allowedCharSet[buf[i] % allowedCharSet.Length]);
                }
            }
            return result.ToString();
        }
    }
}