﻿using System;

namespace Calculator
{
    /// <summary>
    /// Implementation of the functionality of the calculator
    /// </summary>
    public class Calculator
    {
        private const int maxNumberLength = 10;
        private bool equalButtonPressed;
        private string result;
        private string operation;
        private string secondOperand;

        public Calculator()
        {
            result = "0";
            secondOperand = "";
            operation = "";
        }

        /// <summary>
        /// Output of operands and operations on the screen
        /// </summary>
        public string GetScreenText() => result + " " + operation + "\r\n" + secondOperand;

        /// <summary>
        /// Adding a number
        /// </summary>
        public void AddNumber(string number)
        {
            if (equalButtonPressed && operation == "")
            {
                result = "0";
                equalButtonPressed = false;
            }

            if (operation == "")
            {
                if (result == "0")
                {
                    if (number == "0")
                    {
                        return;
                    }

                    result = number;
                    return;
                }
                else if (result.Length == maxNumberLength)
                {
                    return;
                }

                result += number;
                return;
            }

            if (secondOperand == "0")
            {
                secondOperand = "";
            }
            else if (secondOperand == "0" && number == "0")
            {
                return;
            }
            else if (secondOperand.Length == maxNumberLength)
            {
                return;
            }
            
            secondOperand += number;
        }

        /// <summary>
        /// Reaction to arithmetic buttons
        /// </summary>
        public void OperationButton(string operation)
        {
            if (operation == "" || secondOperand == "")
            {
                this.operation = operation;
                return;
            }

            CalculateResult();
            this.operation = operation;
        }

        /// <summary>
        /// Reaction to the button "="
        /// </summary>
        public void EqualButton()
        {
            if (operation == "" || secondOperand == "")
            {
                return;
            }
            
            CalculateResult();
            operation = "";
            equalButtonPressed = true;
        }

        /// <summary>
        /// Change of sign to the opposite
        /// </summary>
        public void ChangeSign()
        {
            if (secondOperand != "")
            {
                return;
            }

            if (result[0] == '-')
            {
                result = result.Substring(1);
            }
            else
            {
                if (result[0] != '0')
                {
                    result = "-" + result;
                }
            }
        }

        /// <summary>
        /// Cleaning the screen
        /// </summary>
        public void Clear()
        {
            result = "0";
            operation = "";
            secondOperand = "";
        }

        /// <summary>
        /// Deleting the last character of a number
        /// </summary>
        public void ClearLastCharacter()
        {
            if (operation == "")
            {
                if (result.Length > 1)
                {
                    result = result.Remove(result.Length - 1);
                }
                else
                {
                    result = "0";
                }
            }
            else
            {
                if (secondOperand.Length > 1)
                {
                    secondOperand = secondOperand.Remove(secondOperand.Length - 1);
                }
                else
                {
                    secondOperand = "0";
                }
            }
        }

        /// <summary>
        /// Getting the fractional part of a number
        /// </summary>
        public void GetFraction()
        {
            if (operation == "")
            {
                result += ",";
            }
            else
            {
                secondOperand += ",";
            }
        }

        /// <summary>
        /// Counting the result of an expression
        /// </summary>
        public void CalculateResult()
        {
            var firstNumber = Convert.ToDouble(this.result);
            var secondNumber = Convert.ToDouble(this.secondOperand);
            double result = 0;
            switch (operation)
            {
                case "+":
                    result = firstNumber + secondNumber;
                    break;
                case "-":
                    result = firstNumber - secondNumber;
                    break;
                case "*":
                    result = firstNumber * secondNumber;
                    break;
                case "/":
                    if (Math.Abs(secondNumber) < 0.000001)
                    {
                        throw new DivideByZeroException("Division by zero is impossible.");
                    }

                    result = firstNumber / secondNumber;
                    break;
            }

            if (result > Math.Pow(10, 10))
            {
                throw new ExceedingNumericalRangeException("Result is too big.");
            }

            secondOperand = "";
            this.result = result.ToString();
        }

        /// <summary>
        /// Getting calculation result for testing
        /// </summary>
        public string GetResult() => result;
    }
}