﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dealership.Common.Enums;
using Dealership.Contracts;
using Dealership.Common;
using System.Text.RegularExpressions;


namespace Dealership.Models
{
    class User : IUser
    {
        private readonly string firstName;
        private readonly string lastName;
        private readonly string password; //in our case, there is no method 
        private readonly string username; //to modify the password or username, thus they could be readonly
        private IList<IVehicle> vehicles;

        public User(string username, string firstName, string lastName, string password, string role)
        {
            Validator.ValidateIntRange(username.Length, Constants.MinNameLength, Constants.MaxNameLength,
                string.Format(Constants.StringMustBeBetweenMinAndMax,
                "Username", Constants.MinNameLength, Constants.MaxNameLength));

            Validator.ValidateSymbols(username, Constants.UsernamePattern,
                string.Format(Constants.InvalidSymbols, "Username"));

            Validator.ValidateIntRange(firstName.Length, Constants.MinNameLength, Constants.MaxNameLength,
                string.Format(Constants.StringMustBeBetweenMinAndMax,
                "Firstname", Constants.MinNameLength, Constants.MaxNameLength));

            Validator.ValidateIntRange(lastName.Length, Constants.MinNameLength, Constants.MaxNameLength,
                string.Format(Constants.StringMustBeBetweenMinAndMax,
                "Lastname", Constants.MinNameLength, Constants.MaxNameLength));

            Validator.ValidateSymbols(password, Constants.PasswordPattern,
                string.Format(Constants.InvalidSymbols, "Password"));

            Validator.ValidateIntRange(password.Length, Constants.MinPasswordLength, Constants.MaxPasswordLength,
                string.Format(Constants.StringMustBeBetweenMinAndMax,
                "Password", Constants.MinPasswordLength, Constants.MaxPasswordLength));

            foreach (var roleType in (Role[])Enum.GetValues(typeof(Role)))
            {
                if (roleType.ToString() == role)
                {
                    this.Role = roleType;
                }
            }

            this.username = username;
            this.password = password;
            this.firstName = firstName;
            this.lastName = lastName;
            this.vehicles = new List<IVehicle>();
        }

        public string FirstName
        {
            get
            {
                return this.firstName;
            }
        }

        public string LastName
        {
            get
            {
                return this.lastName;
            }
        }

        public string Password
        {
            get
            {
                return this.password;
            }
        }

        public Role Role
        {
            get; private set;
        }

        public string Username
        {
            get
            {
                return this.username;
            }
        }

        public IList<IVehicle> Vehicles
        {
            get
            {
                return new List<IVehicle>(this.vehicles);
            }
        }


        public void AddComment(IComment commentToAdd, IVehicle vehicleToAddComment)
        {
            Validator.ValidateNull(commentToAdd, Constants.CommentCannotBeNull);
            Validator.ValidateNull(vehicleToAddComment, Constants.VehicleCannotBeNull);

            commentToAdd.Author = this.Username;
            vehicleToAddComment.Comments.Add(commentToAdd);
        }

        public void AddVehicle(IVehicle vehicle)
        {
            Validator.ValidateNull(vehicle,
                Constants.VehicleCannotBeNull);

            if (this.Role==Role.Admin)
            {
                throw new ArgumentException(Constants.AdminCannotAddVehicles);
            }

            if (this.Vehicles.Count==5)
            {
                if (this.Role!=Role.VIP)
                {
                    throw new ArgumentException(
                        string.Format(Constants.NotAnVipUserVehiclesAdd, Constants.MaxVehiclesToAdd));
                }
            }
            this.vehicles.Add(vehicle);
        }

        public string PrintVehicles()
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("--USER {0}--", this.Username).AppendLine();

            if (this.Vehicles.Count==0)
            {
                sb.AppendLine("--NO VEHICLES--");
            }

            else
            {
                int indexes = 1;
                foreach (var vehicle in this.Vehicles)
                {
                    sb.AppendFormat("{0}. ", indexes);
                    sb.AppendLine(vehicle.ToString());
                    indexes++;
                }

            }

            return sb.ToString().TrimEnd('\r', '\n');
        }

        public void RemoveComment(IComment commentToRemove, IVehicle vehicleToRemoveComment)
        {
            Validator.ValidateNull(commentToRemove, Constants.CommentCannotBeNull);
            Validator.ValidateNull(vehicleToRemoveComment, Constants.VehicleCannotBeNull);

            if (this.Username!=commentToRemove.Author)
            {
                throw new ArgumentException(Constants.YouAreNotTheAuthor);
            }

            commentToRemove.Author = this.Username;
            vehicleToRemoveComment.Comments.Remove(commentToRemove);

        }

        public void RemoveVehicle(IVehicle vehicle)
        {
            Validator.ValidateNull(vehicle,
                Constants.VehicleCannotBeNull);
            this.vehicles.Remove(vehicle);

        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("Username: {0}, FullName: {1} {2}, Role: {3}",
                this.Username, this.FirstName, this.LastName, this.Role.ToString()).AppendLine();

            return sb.ToString().TrimEnd('\r', '\n'); 
        }
    }
}
