import java.util.Arrays;

import java.awt.CardLayout;
public class Main {
    public static void main(String args[]) {
        Vehicle vehicle = new Vehicle(200, 20);
        Car car                 = new Car(2000, 100);
        Bike bike             = new Bike(300, 60);
        Truck truck         = new Truck(4000, 80);

        System.out.println(truck);
        // vehicle.display();
        // car.display();
        // bike.display();
        // truck.display();
        System.out.println();

        Garage garage = new Garage(new Vehicle[] {vehicle, car, bike, truck});
        garage.count();
        System.out.println();
        System.out.println(garage);
        System.out.println();
        // System.out.println("Popped out of garage: " + garage.popVehicle());
        System.out.println(garage.popVehicle());
        System.out.println();
        // System.out.println(garage.addVehicle(new Car(1400, 120)));
        garage.addVehicle(new Car(1400, 120));
        System.out.println(garage);
    }
}

class Vehicle {
    protected int _mass;
    protected int _velocity;

    public Vehicle(int mass, int velocity) {
        _mass = mass;
        _velocity = velocity;
    }

    public int getMass() { return _mass; }
    public void setMass(int mass) { _mass = mass; }

    public int getVelocity() { return _velocity; }
    public void setVelocity(int velocity) { _velocity = velocity; }
    
    public void move() { System.out.println(_velocity); }

    public void display() {
        System.out.printf("%s: mass=%d, velocity=%d\n",
                          this.getClass().getSimpleName(), _mass, _velocity);
    }

    @Override
    public String toString() {
        String result = "{\"type\": \"" + this.getClass().getSimpleName()
                                        + "\", \"mass\": " + _mass
                                        + ", \"velocity\": " + _velocity + "}";
        return result;
    }
}

class Car extends Vehicle {
    public Car(int mass, int velocity) {
        super(mass, velocity);
    }

    public void accelerate(int velocity) { _velocity += velocity; }
}

class Bike extends Vehicle {
    public Bike(int mass, int velocity) {
        super(mass, velocity);
    }

    public void accelerate(int velocity) { _velocity += velocity; }
}

class Truck extends Vehicle {
    public Truck(int mass, int velocity) {
        super(mass, velocity);
    }

    public void loadCargo(int mass) {
        _mass += mass;
        _velocity -= mass; // One kg of cargo makes Vehicle 1 km/h slower
    }
}

class Garage {
    private Vehicle[] _vehicles;

    public Garage() {
        _vehicles = new Vehicle[0];
    }

    public Garage(Vehicle[] vehicles) {
        _vehicles = vehicles != null ? vehicles : new Vehicle[0];
    }

    public Vehicle[] getVehicles() { return _vehicles; }
    public void setVehicles(Vehicle[] vehicles) {
        _vehicles = vehicles != null ? vehicles : new Vehicle[0];
    }

    public Vehicle getVehicle(int index) {
        if (index >= 0 && index < _vehicles.length) {
            return _vehicles[index];
        }
        return null;
    }
    public void setVehicle(int index, Vehicle vehicle) {
        if (index >= 0 && index < _vehicles.length && vehicle != null) {
            _vehicles[index] = vehicle;
        }
    }

    public boolean addVehicle(Vehicle vehicle) {
        if (vehicle != null) {
            Vehicle[] newVehicles = Arrays.copyOf(_vehicles, _vehicles.length + 1);
            newVehicles[newVehicles.length - 1] = vehicle;
            _vehicles = newVehicles;
            return true;
        }
        return false;
    }

    public Vehicle popVehicle() {
        if (_vehicles.length > 0) {
            Vehicle[] newVehicles = Arrays.copyOf(_vehicles, _vehicles.length - 1);
            Vehicle vehicleToReturn = _vehicles[_vehicles.length - 1];
            _vehicles = newVehicles;
            return vehicleToReturn;
        }
        return null;
    }

    public void count() {
        int carCount = 0;
        int bikeCount = 0;
        int truckCount = 0;
        int otherCount = 0;
        for (Vehicle vehicle : _vehicles) {
            if (vehicle instanceof Car) carCount++;
            else if (vehicle instanceof Bike) bikeCount++;
            else if (vehicle instanceof Truck) truckCount++;
            else otherCount++;
        }

        System.out.printf("{\"Garage\": {\"Cars\": %d, \"Bikes\": %d, \"Trucks\": %d, \"Others\": %d}}\n",
                                           carCount, bikeCount, truckCount, otherCount);
    }

    public void setVehicleVelocity(int index, int velocity) {
        if (index >= 0 && index < _vehicles.length) 
            _vehicles[index].setVelocity(velocity);
    }

    @Override
    public String toString() {
        String result = "{\"" + this.getClass().getSimpleName()
                        + "\": {\"size\":" + _vehicles.length
                        + ", \"vehicles\": [";
        for (Vehicle vehicle : _vehicles) {
            result += vehicle.toString() + ",";
        }
        result = result.substring(0, result.length() - 1) + "]}}";
        return result;
    }
}
