#include <iostream>

using namespace std;

class Report {
  public:
    Report(ostream &s) : stream(s) {};
    virtual void print() const = 0;
  protected:
    ostream &stream;
};

class Engine {
  public:
    Engine(int cyl = 4, int cap = 2000, int pow = 150);
    bool start();
    bool stop();

  private:
    bool status;
    int fuel;
    int cylinders;
    int capacity;
    int power;
};

class Transmission {
  public:
    Transmission(int g = 6);

  private:
    int gears;
};


class Vehicle {
  public:
    Vehicle(int w = 0, int l = 0, int h = 0);
    virtual bool start(); 
    virtual bool stop();
    virtual int turn(int dir);
    
  protected:
    Engine engine;
    Transmission transmission;
    int mileage;

  private:
    int weight;
    int length;
    int height;
};


class Car : public Vehicle, public Report {
  public:
    Car(int w = 4);
    bool start();
    bool stop();
    void print() const;

  private:
    int turn(int dir);
    int lights;
    int wheels;
};


class VendingMachine {
  public:
    VendingMachine(int s = 0);
    
  private:
    int supplies;  
};


class CofeeMachine : public VendingMachine, public Report {
  public:
    CofeeMachine(int c = 0);
    void print() const;
    
  private:
    int supplies; 
    int cofee; 
};


Engine::Engine(int cyl, int cap, int pow) {
    this->status = true;
    this->cylinders = cyl;
    this->capacity = cap;
    this->power = pow;
}

bool Engine::start() {
    cout << "Engine start" << endl;
    return this->status;
}

bool Engine::stop() {
    cout << "Engine stop" << endl;
    return true;
}

Transmission::Transmission(int g) {
    this->gears = g;
}

Vehicle::Vehicle(int w, int l, int h) {
    this->weight = w;
    this->length = l;
    this->height = h;
}

bool Vehicle::start() {
    cout << "Vehicle start" << endl;
    return engine.start();
}

bool Vehicle::stop() {
    cout << "Vehicle stop" << endl;
    return engine.stop();
}

int Vehicle::turn(int dir) {
    cout << "Vehicle turns " << (dir ? "right" : "left") << endl;    
    return 0;
}

Car::Car(int m) : Vehicle(1700, 250, 160), Report(cout) {
    this->mileage = m;
}

bool Car::start() {
    cout << "Car start" << endl;
    if (Vehicle::start()) {
        this->lights = 1;
        return true;
    } else
        return false;
}

bool Car::stop() {
    cout << "Car stop" << endl;    
    this->lights = 0;
    return Vehicle::stop();
}

int Car::turn(int dir) {
    cout << "Car turns " << (dir ? "right" : "left") << endl;    
    return 0;
}

void Car::print() const {
    this->stream << "Mileage: " << this->mileage << endl;
}


VendingMachine::VendingMachine(int s) {
    this->supplies = s;
}

CofeeMachine::CofeeMachine(int c) : Report(cout) {
    this->cofee = c;
}

void CofeeMachine::print() const {
    cout << "Cofee: " << this->cofee << endl;
}

bool run(Vehicle &vehicle) {
    vehicle.start();
    vehicle.turn(0);
    vehicle.turn(1);
    vehicle.stop();
    
    return false;
}

int main() {
    Car c(180000);
    CofeeMachine cm(1500);
    
    Report* tab[] = { &c, &cm };

    Vehicle* vtab[] = { &c, &cm };

    for (int i = 0; i < 2; i++)
        tab[i]->print();
    
    
    return 0;
}


