using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using KendoDateSample.Models.Repositories;

namespace KendoDateSample.Models
{
    public class UserModel : IValidatableObject
    {
        #region Constructors

        public UserModel()
        {

        }

        #endregion //Constructors

        #region Database Properties

        private DateTime? _dobUtc;


        [DisplayName("Id#")]
        public int Id { get; set; }

        [DisplayName("Created")]
        [DataType(DataType.Date)]
        public DateTime Created { get; set; }

        [Required(ErrorMessage = "Required")]
        [DisplayName("User Type")]
        public byte UserTypeId { get; set; }

        [Required(ErrorMessage = "Required")]
        [StringLength(50)]
        [DisplayName("First Name")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "Required")]
        [StringLength(50)]
        [DisplayName("Last Name")]
        public string LastName { get; set; }

        [StringLength(100)]
        [DataType(DataType.EmailAddress)]
        [DisplayName("Email")]
        public string Email { get; set; }

        [StringLength(100)]
        [DisplayName("Password")]
        public string Password { get; set; }

        [StringLength(100)]
        [DisplayName("Address Line1")]
        public string AddressLine1 { get; set; }

        [StringLength(100)]
        [DisplayName("Address Line2")]
        public string AddressLine2 { get; set; }

        [StringLength(50)]
        [DisplayName("City")]
        public string City { get; set; }

        [StringLength(2)]
        [DisplayName("State")]
        public string StateId { get; set; }

        [StringLength(10)]
        [DisplayName("Zipcode")]
        public string Zipcode { get; set; }

        [StringLength(20)]
        [DataType(DataType.PhoneNumber)]
        [DisplayName("Phone")]
        public string Phone1 { get; set; }

        [DisplayName("Sales Manager")]
        public int SalesManagerId { get; set; }

        [DisplayName("Sales Rep")]
        public int SalesRepId { get; set; }

        [DisplayName("Doctor")]
        public int DoctorId { get; set; }

        [DisplayName("Active?")]
        public bool IsActive { get; set; }

        public bool UseUtc { get; set; }

        [DisplayName("D.O.B.")]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        [DataType(DataType.Date)]
        public DateTime? DOB2 { get; set; }

        [DisplayName("D.O.B.")]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        [DataType(DataType.Date)]
        public DateTime? DOB
        {
            get { return _dobUtc; }
            set
            {
                if (value.HasValue)
                    this._dobUtc = new DateTime(value.Value.Ticks, DateTimeKind.Utc);
                else
                    this._dobUtc = null;
            }
        }

        [DisplayName("Carrier")]
        public byte CarrierId { get; set; }

        #endregion //Database Properties

        #region Custom Properties

        string _passwordUnEncrypted = string.Empty;
        string _passwordConfirm = string.Empty;

        public string DobString
        {
            get { return DOB.HasValue ? DOB.Value.ToShortDateString() : string.Empty; }
        }

        public string PhoneFormatted
        {
            get { return Phone1.FormatAsPhoneNumber(); }
        }

        public string FullName
        {
            get { 
                var firstname = FirstName ?? string.Empty;
                var lastname = LastName ?? string.Empty;

                //if (!SessionManagement.CurrentUser.GetIsPharmacy() && firstname.Length > 1)
                //firstname = string.Format("{0}.", firstname.Substring(0, 1));
                    

                return string.Format("{0}, {1}", lastname, firstname);
            }
        }

        [Display(Name = "Email Credentials?")]
        public bool IsEmailCredentials { get; set; }

        //[Required(ErrorMessage = " ")]
        //[RegularExpression(@"^.*(?=.{8,})(?=.*[\d]).*$", ErrorMessage = "! Passwords must be at least 8 characters & 1 digit")]
        [DataType(DataType.Password)]
        //[StringLength(15, MinimumLength = 8)]
        [Display(Name = "Password")]
        public string PasswordUnEncrypted
        {
            get
            {
                if (string.IsNullOrEmpty(_passwordUnEncrypted) &&
                    !string.IsNullOrEmpty(Password))
                {
                    var encryption = new Encryption();
                    _passwordUnEncrypted = encryption.DecryptString(Password);
                }

                return _passwordUnEncrypted;
            }
            set
            {
                _passwordUnEncrypted = value;
            }
        }

        //[Required(ErrorMessage = " ")]
        //[RegularExpression(@"^.*(?=.{8,})(?=.*[\d]).*$", ErrorMessage = "! Passwords must be at least 8 characters & 1 digit")]
        [DataType(DataType.Password)]
        //[StringLength(15, MinimumLength = 8)]
        [Display(Name = "Confirm PW")]
        public string PasswordConfirm
        {
            get
            {
                if (string.IsNullOrEmpty(_passwordConfirm) &&
                    !string.IsNullOrEmpty(Password))
                {
                    var encryption = new Encryption();
                    _passwordConfirm = encryption.DecryptString(Password);
                }

                return _passwordConfirm;
            }
            set
            {
                _passwordConfirm = value;
            }
        }

        [Display(Name = "User Type")]
        public string UserTypeName { get; set; }

        #endregion //Custom Properties

        #region Search Properties

        public int PrescriptionId { get; set; }

        [DisplayName("RX #")]
        public string RXNumber { get; set; }

        [DisplayName("On Hold?")]
        public bool IsHold { get; set; }

        #endregion //Search Properties

        #region Helper Methods

        public string GetTextMessageEmailAddress()
        {
            var result = string.Empty;

            if (CarrierId > 0)
            {
                var carrier = MobileCarrierRepository.One(CarrierId);
                var carrierSuffix = (carrier != null ? carrier.Suffix : string.Empty);
                var phone = (!string.IsNullOrEmpty(Phone1) ? Phone1 : string.Empty);
                result = string.Format("{0}{1}", Phone1, carrierSuffix);
            }

            return result;
        }

        public bool GetIsAdministrator()
        {
            return UserTypeId == (short)Enums.UserTypes.Administrator;
        }

        public bool GetIsPharmacy()
        {
            var types = new short[] { (short)Enums.UserTypes.Pharmacist, (short)Enums.UserTypes.Administrator };
            return types.Contains(UserTypeId);
        }

        #endregion //Helper Methods

        #region Validation

        public bool ValidateEmail()
        {
            if (!string.IsNullOrEmpty(Email))
            {
                var duplicatesFound = UserRepository.Any(x => x.Id != this.Id && x.Email == this.Email);
                return !duplicatesFound;
            }

            return true;
        }

        public bool ValidatePassword()
        {
            if (!string.IsNullOrEmpty(PasswordUnEncrypted))
                return PasswordUnEncrypted.IsValidPassword();

            return true;
        }

        public bool ValidatePasswordConfirm()
        {
            if (!string.IsNullOrEmpty(PasswordConfirm))
                return PasswordConfirm == PasswordUnEncrypted;

            return true;
        }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            var isValid = ValidateEmail();

            if (!isValid)
                yield return new ValidationResult("Email already exists.", new[] { "Email" });

            isValid = ValidatePassword();

            if (!isValid)
                yield return new ValidationResult("Passwords must be at least 8 characters & 1 digit.", new[] { "PasswordUnEncrypted" });

            isValid = ValidatePasswordConfirm();

            if (!isValid)
                yield return new ValidationResult("Password and Confirm PW do not match.", new[] { "PasswordConfirm" });
        }

        #endregion //Validation
    }
}