#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "pico/multicore.h"
#include "hardware/adc.h"
#include <stdbool.h>
#include <iostream>

class TrafficLight {
public:
 enum TrafficState {
        RED,
        YELLOW,
        GREEN,
    };
    TrafficLight(int redPin, int yellowPin, int greenPin, int buttonPin , int pedestrianRedPin, int pedestrianGreenPin, int buzzer) {
        this->redPin = redPin;
        this->yellowPin = yellowPin;
        this->greenPin = greenPin;
        this->buttonPin = buttonPin;
        this->pedestrianRedPin = pedestrianRedPin;
        this->pedestrianGreenPin = pedestrianGreenPin;
        this->buzzer = buzzer;

        setPedestrianLightRed();
        gpio_put(buzzer, 0);
        currentState = GREEN;

        gpio_init(redPin);
        gpio_set_dir(redPin, GPIO_OUT);
        gpio_init(yellowPin);
        gpio_set_dir(yellowPin, GPIO_OUT);
        gpio_init(greenPin);
        gpio_set_dir(greenPin, GPIO_OUT);
        gpio_init(buttonPin);
        gpio_set_dir(buttonPin, GPIO_IN);
        gpio_pull_down(buttonPin);
        gpio_init(pedestrianRedPin);
        gpio_set_dir(pedestrianRedPin, GPIO_OUT);
        gpio_init(pedestrianGreenPin);
        gpio_set_dir(pedestrianGreenPin, GPIO_OUT);
        gpio_init(buzzer);
        gpio_set_dir(buzzer, GPIO_OUT);

        stdio_init_all();
    }

        void run() {
        while (true) {

            switch (currentState) {
                case RED:
                    for (int i = 0; i < 50; i++) {
                        sleep_ms(10); 
                        if (gpio_get(buttonPin) == true) {
                        setTrafficLightRed();
                        setPedestrianLightRed();
                        setWalk();
                        currentState = GREEN;
                        }

                        else
                        {
                            setTrafficLightRed();
                            setPedestrianLightRed();
                            sleep_ms(100);
                            currentState = GREEN;
                        }

                    }
                    break;

                case YELLOW:
                    for (int i = 0; i < 20; i++) {
                        sleep_ms(10); 
                        if (gpio_get(buttonPin) == true) {
                            sleep_ms(2000);
                            setTrafficLightRed();
                            setPedestrianLightRed();
                            sleep_ms(5000);
                            setWalk();
                            currentState = GREEN;
                        }

                        else
                        {
                            setTrafficLightYellow();
                            setPedestrianLightRed();
                            sleep_ms(100);
                            currentState = RED;
                        }

                    }
                    break;

                case GREEN:
                    
                    for (int i = 0; i < 50; i++) {
                        sleep_ms(10); 
                        if (gpio_get(buttonPin) == true) {
                            sleep_ms(5000);
                            setTrafficLightYellow();
                            setPedestrianLightRed();
                            sleep_ms(2000);
                            setTrafficLightRed();
                            setPedestrianLightRed();
                            sleep_ms(5000);
                            setWalk();
                            currentState = GREEN;

                        }

                        else
                        {
                            setTrafficLightGreen();
                            setPedestrianLightRed();
                            sleep_ms(100);
                            currentState = YELLOW;
                        }

                    }
                    break;
            }
        }
    }


private:
    int redPin;
    int yellowPin;
    int greenPin;
    int buttonPin;
    int pedestrianRedPin;
    int pedestrianGreenPin;
    int buzzer;
    static const uint8_t button = 16;

    void setTrafficLightRed() {
        gpio_put(redPin, 1);
        gpio_put(yellowPin, 0);
        gpio_put(greenPin, 0);
    }

    void setTrafficLightYellow() {
        gpio_put(redPin, 0);
        gpio_put(yellowPin, 1);
        gpio_put(greenPin, 0);
    }

    void setTrafficLightGreen() {
        gpio_put(redPin, 0);
        gpio_put(yellowPin, 0);
        gpio_put(greenPin, 1);
    }

    void setWalk() {
        gpio_put(pedestrianRedPin, 0);
        for (int i = 0; i < 5; i++) {
            gpio_put(pedestrianGreenPin, 1);
            gpio_put(buzzer, 1);
            sleep_ms(500);
            gpio_put(pedestrianGreenPin, 0);
            gpio_put(buzzer, 1);
            sleep_ms(500);
        }
    }

    void setPedestrianLightRed() {
        gpio_put(pedestrianRedPin, 1);
        gpio_put(pedestrianGreenPin, 0);
    }

    void setPedestrianLightGreen() {
        gpio_put(pedestrianRedPin, 0);
        gpio_put(pedestrianGreenPin, 1);
    }

    void setPedestrianLightBlinkGreen() {
        for (int i = 0; i < 5; i++) {
            gpio_put(pedestrianGreenPin, 1);
            sleep_ms(500);
            gpio_put(pedestrianGreenPin, 0);
            sleep_ms(500);
        }
    }

    void setPedestrianWalkBuzzer() {
        gpio_put(buzzer, 1);
        sleep_ms(5000);
    }
    TrafficState currentState;
};

int main() {
    const int redPin = 15;                     
    const int yellowPin = 14;                  
    const int greenPin = 13;                   
    const int buttonPin = 16;                  
    const int pedestrianRedPin = 17;           
    const int pedestrianGreenPin = 18;         
    const int buzzer = 19;

    TrafficLight trafficLight(redPin, yellowPin, greenPin, buttonPin, pedestrianRedPin, pedestrianGreenPin, buzzer);

    while (true) {
        trafficLight.run();
    }

    return 0;
}
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT