#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>

using namespace std;

float SquareArea();
void CircleArea();

template <class T, typename F>
void GetInput(T *result, const char message[], F &&constraint);

int main()
{
    int option = 0;
    cout << "Willkommen im Flaechenrechner\n Tippen sie \n\t\"1\" für die Flaechenberechengung eines Rechtecks oder \n\t\"2\" für die Berechnung eines Kreises\n";
    GetInput(&option, "Option: ", [](int val)
             { return (val > 0 && val < 3); });

    switch (option)
    {
    case 1:
    {
        float result = SquareArea();
        cout << "Die Flaeche betraegt " << result << " Einheiten\n";
        break;
    }
    case 2:
        CircleArea();
        break;
    default:
        break;
    }
}

template <class T, typename F>
void GetInput(T *result, const char message[], F &&constraint)
{
    while (true)
    {
        cout << message;
        cin >> *result;
        if (cin.fail())
        {
            cout << "\nFehler bei der Eingabe, bitte veruschen Sie es noch einmal\n";
            cin.clear();
            cin.ignore();
        }
        else if (!constraint(*result))
        {
            cout << "\nDer eingegebene Wert entspricht nicht den Anforderungen\n";
        }
        else
            break;
    }
}

float SquareArea()
{
    float width = 0, height = 0;
    cout << "Rechteck berechnen. Bitte Daten eingeben. \n";
    GetInput(&width, "Breite: ", [](float val)
             { return val>0;  });
    GetInput(&height, "Hoehe: ", [](float val)
             { return val>0;  });
    return (width * height);
}

void CircleArea()
{
    float rad = 0;
    cout << "Kreis berechnen. Bitte Daten eingeben. \n";
    GetInput(&rad, "Radius: ", [](float val)
             { return val>0; });
    cout << "Die Flaeche betraegt " << (M_PI * pow(rad, 2)) << " Einheiten\n";
}