#include <iostream> // Basic library
#include <cstdlib> // used with system() functions
#include <windows.h> // used to convert console output
#include <cmath> // used for mathamatical functions
#include <ctime> // used to access live time
using namespace std;

class Calculator
{
private:
    int options;
    float val1;
    float val2;

public:
    Calculator()
    {
    }

    long long factorial(int n)
    {
        if (n <= 1)
        {
            return 1;
        }
        return n * factorial(n - 1);
    }

    void info()
    {
        cout<<"<========== Information ==========>"<<endl;
        cout<<"Name: Calculator\nVersion: 1.3\nDeveloped by: AJ Developer\n";
        
        // TO print live date and time
        time_t timestamp;
        time(&timestamp);
        cout <<"Date: "<< ctime(&timestamp);
        cout<<"<========== Information ==========>\n\n";
    }

    void opt()
    {
        cout << "Choose your options:\n1) Addition\n2) Subtraction\n3) Multiplication\n4) Division\n5) Power\n6) Square root\n7) Factorial\n8) Log\n0) Exit" << endl;
        cin >> options;
    }

    bool check()
    {
        if (options < 0 || options > 8)
        {
            cout<<"<========== Error ==========>"<<endl;
            cout << "Please choose the number from 0 to 8" << endl;
            return false;
        }

        return true;
    }

    void wrong_Input_1()
    {
        while(!(cin>>val1))
        {
            cout<<"Error: Please enter numbers only\n";
            cin.clear();
            cin.ignore(10000, '\n');

            cout<<"\nTry Again: ";
        }
    }

    void wrong_Input_2()
    {
        while(!(cin>>val2))
        {
            cout<<"Error: Please enter numbers only\n";
            cin.clear();
            cin.ignore(10000, '\n');

            cout<<"\nTry Again: ";
        }
    }

    bool operation()
    {
        // For exit
        if (options == 0)
        {
            {
                cout << "<========== Thanks for using our calculator ==========>" << endl;
                system("pause");
                return false;
            }
            return true;
        }

        // For functions that requires two values
        else if (options >= 1 && options <= 5)
        {

            // Addition
            if (options == 1)
            {
                cout<<"\n<========== Addition ==========>"<<endl;
                cout << "\nEnter your first value:" << endl;
                wrong_Input_1();
                cout << "Enter your second value:" << endl;
                wrong_Input_2();
                cout<<"\n<========== Result ==========>"<<endl;
                cout << val1 << " + " << val2 << " = " << val1 + val2 << endl;
            }
            
            // Subtraction
            else if (options == 2)
            {
                cout<<"\n<========== Subtraction ==========>"<<endl;
                cout << "\nEnter your first value:" << endl;
                wrong_Input_1();
                cout << "Enter your second value:" << endl;
                wrong_Input_2();
                cout<<"\n<========== Result ==========>"<<endl;
                cout << val1 << " - " << val2 << " = " << val1 - val2 << endl;
            }
            
            // Multiplication
            else if (options == 3)
            {
                cout<<"\n<========== Multiplication ==========>"<<endl;
                cout << "\nEnter your first value:" << endl;
                wrong_Input_1();
                cout << "Enter your second value:" << endl;
                wrong_Input_2();
                cout<<"\n<========== Result ==========>"<<endl;
                cout << val1 << " X " << val2 << " = " << val1 * val2 << endl;
            }
            
            // Division
            else if (options == 4)
            {
                cout<<"\n<========== Division ==========>"<<endl;
                cout << "\nEnter your first value:" << endl;
                wrong_Input_1();
                if (val1 < 0)
                {
                    cout<<"\n<========== Error ==========>"<<endl;
                    cout << "Negative numbers not allowed" << endl;
                    return 1;
                }
                else
                {
                    cout << "Enter your second value:" << endl;
                    wrong_Input_2();
                    if (val2 == 0)
                    {
                        cout<<"\n<========== Error ==========>"<<endl;
                        cout << "Division by 0 not allowed" << endl;
                        return 1;
                    }
                    else if (val2 < 0)
                    {
                        cout<<"\n<========== Error ==========>"<<endl;
                        cout << "Negative numbers not allowed" << endl;
                        return 1;
                    }
                    else
                    {
                        cout<<"\n<========== Result ==========>"<<endl;
                        div_t Div = div(int(val1),int(val2));
                        cout<<"Quiotent: "<<Div.quot<<endl;
                        cout<<"Remainder: "<<Div.rem<<endl;
                        // cout << val1 << " ÷ " << val2 << " = " << float(val1) / float(val2) << endl;
                    }
                }
            }
            
            // Power
            if (options == 5)
            {
                cout<<"\n<========== Power ==========>"<<endl;
                cout << "\nEnter your base:" << endl;
                wrong_Input_1();
                cout << "\nEnter your exponent:" << endl;
                wrong_Input_2();
                cout<<"\n<========== Result ==========>"<<endl;
                cout << val1 << " ^ " << val2<<" = " << pow(val1, val2) << endl;
            }
        }
        
        // For operations that requires one value
        else if (options >= 6 && options <= 8)
        {
            
            
            // Square root
            if (options == 6)
            {
                cout<<"\n<========== Square root ==========>"<<endl;
                cout << "\nEnter your value:" << endl;
                wrong_Input_1();
                if(val1 < 0){
                    cout<<"\n<========== Error ==========>"<<endl;
                    cout<<"Negative numbers are not allowed"<<endl;
                    return 1;
                }
                else{
                    cout<<"\n<========== Result ==========>"<<endl;
                    cout << "√" << val1 << " = " << sqrt(val1) << endl;
                }
            }
            
            // Factorial
            else if (options == 7)
            {
                cout<<"\n<========== Factorial ==========>"<<endl;
                cout << "\nEnter your value:" << endl;
                wrong_Input_1();
                if(val1>20){
                    cout<<"\n<========== Error ==========>"<<endl;
                    cout<<"Maximum 20 allowed"<<endl;
                    return 1;
                }
                else if(val1<0){
                    cout<<"\n<========== Error ==========>"<<endl;
                    cout<<"Negative numbers are not allowed"<<endl;
                    return 1;
                }
                else{
                    cout<<"\n<========== Result ==========>"<<endl;
                    cout << val1 << "!" << " = " << factorial(int(val1)) << endl;
                }
            }
            
            // For log
            else if(options == 8){
                cout<<"\n<========== Log ==========>"<<endl;
                cout<<"\nEnter your value:"<<endl;
                wrong_Input_1();
                if(val1<=0){
                    cout<<"\n<========== Error ==========>"<<endl;
                    cout<<"Please enter positive integers"<<endl;
                    return 1;
                }
                
                else if(val1 > 10000)
                {
                    cout<<"\n<========== Error ==========>"<<endl;
                    cout<<"Limit Exceed: Maximum Value = 1000"<<endl;
                    return 1;
                }
                else{
                    cout<<"\n<========== Result ==========>"<<endl;
                    cout<<"log "<<val1<<" = "<<long(log(val1))<<endl;
                }
            }
        }
        return true;
    }
    
    ~Calculator()
    {
    }
};

int main()
{
    SetConsoleOutputCP(CP_UTF8); // Used with #include<windows.h>
    Calculator obj;
    
    
    while (true)
    {
        system("cls"); // To clear the screen after every operation
        obj.info();
        obj.opt();
        
        if (!obj.check())
        continue;
        
        if (!obj.operation())
        break;
        
        system("pause"); // To hold the output console
    }
    return 0;
}