#ifndef SETOFSHAPES_FIGURE_H
#define SETOFSHAPES_FIGURE_H
#include <typeinfo>
#include <string>
#include <iostream>
#include <memory>
#include <sstream>
#include <cmath>

class Figure {
 public:
    virtual std::string Name() {
        return typeid(*this).name();
    }

    virtual double Perimeter() {
        return 1;
    }

    virtual double Area() {
        return 1;
    }
};

class Triangle : public Figure {
    int a, b, c;
    std::string name = "TRIANGLE";
 public:
    Triangle(int a, int b, int c) : a(a), b(b), c(c) {}

    std::string Name() {
        return name;
    }

    double Perimeter() {
        return a+b+c;
    }

    double Area() {
        int p = Perimeter()/2;
        return sqrt(p*(p-a)*(p-b)*(p-c));
    }
};

class Rect : public Figure {
    int width, height;
    std::string name = "RECT";
 public:
    Rect(int width, int height) : width(width), height(height) {}

    std::string Name() {
        return name;
    }

    double Perimeter() {
        return (width+height)*2;
    }

    double Area() {
        return width*height;
    }
};

class Circle : public Figure {
    int r;
    std::string name = "CIRCLE";
 public:
    explicit Circle(int r): r(r) {}

    std::string Name() {
        return name;
    }

    double Perimeter() {
        return 2*3.14*r;
    }

    double Area() {
        return 3.14*pow(r, 2);
    }
};

std::shared_ptr<Figure> CreateFigure(std::istringstream &fig) {
    std::string abc;
    fig >> abc;
    if (abc == "TRIANGLE") {
        int a, b, c;
        fig >> a >> b >> c;
        std::shared_ptr<Triangle> result(new Triangle(a, b, c));
        return result;
    } else if (abc == "RECT") {
        int width, height;
        fig >> width >> height;
        std::shared_ptr<Rect> result(new Rect(width, height));
        return result;
    } else if (abc == "CIRCLE") {
        int r;
        fig >> r;
        std::shared_ptr<Circle> result(new Circle(r));
        return result;
    }
}

#endif