#include <iostream>

class Wheel {
private:
    int resource = 0;

public:
    Wheel(int resource) {
        this->resource = resource;    
    }

    void use(int time) {
        this->resource -= time;
    }

    int getResource() {
        return resource;
    }
};


#define CAR_WHEELS 4

class Car {
private:
    Wheel* wheels[CAR_WHEELS];
    Wheel* trunk;

public:
    Car() {
        for(int i = 0; i < CAR_WHEELS; i++) {
            wheels[i] = nullptr;
        }
        trunk = nullptr;
    }

    void setWheel(Wheel* wheel, int place) {
        if (place > CAR_WHEELS - 1 || place < 0) return;
        wheels[place] = wheel;
    }

    void setTrunk(Wheel* wheel) {
        this->trunk = wheel;
    }

    void go(int time) {
        for(int i = 0; i < CAR_WHEELS; i++) {
            wheels[i]->use(time);
        }

        std::cout << "go " << time << std::endl;
        this->info();
    }

    void replaceWheelFromTrunk(int place) {
        if (place > CAR_WHEELS - 1 || place < 0) return;
        Wheel* temp = wheels[place];
        wheels[place] = trunk;
        trunk = temp;

        std::cout << "trunk <-> place " << place << std::endl;
        this->info();
    }

    void info() {
        for(int i = 0; i < CAR_WHEELS; i++) {
            std::cout << "P" << i << ": " << wheels[i]->getResource() << " ";
        }

        std::cout << "T" << ": " << trunk->getResource() << " " << std::endl;
        std::cout << std::endl;
    }

};

class CarBuilder {
public:
    Car* build() {
        Car* car = new Car();
        Wheel* wheel;
        int resource = 100;

        for(int i = 0; i < 4; i++) {
            wheel = new Wheel(resource);
            car->setWheel(wheel, i);
        }

        wheel = new Wheel(resource);
        car->setTrunk(wheel);

        return car;
    }
};

class DriverStrategy {
public:
    void execute(Car* car) {

        const int STEPS = 4;    

        int steps[STEPS][2] = {
            {25, 0}, 
            {25, 1}, 
            {25, 2}, 
            {25, 3}, 
        };

        for(int i = 0; i < STEPS; i++) {
            car->go(steps[i][0]);
            car->replaceWheelFromTrunk(steps[i][1]);
        }

        car->go(25);
    }
};

class Driver {
private:
    Car* car;
    DriverStrategy* strategy;
    //Road road;

public: 
    void go() {
        strategy->execute(this->car);
    }

    void setStrategy(DriverStrategy* strategy) {
        this->strategy = strategy;
    }

    void jumpInCar(Car* car) {
        this->car = car;
    }
};


int main(int argc, char* argv[]) {
    CarBuilder builder;
    Car* mycar = builder.build();

    Driver driver;
    DriverStrategy* strategy = new DriverStrategy();
    driver.setStrategy(strategy);
    driver.jumpInCar(mycar);

    mycar->info();
    driver.go();

    return 0;
}
