#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <ESP8266WebServer.h>

// Параметры дисплея
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Пины
#define BUZZER_PIN 14

// Данные для подключения к Wi-Fi по умолчанию
String ssid = "Mesto_Chistoty";
String password = "Mesto13092022";

// Настройка NTP-клиента
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 3600 * 3, 60000);

// Веб-сервер
ESP8266WebServer server(80);

// Время будильника
String alarmTime = "--:--";
bool alarmActivated = false;

// Контроль времени для отображения IP
unsigned long displayStart;
bool showDate = false;

// Структура для снежинок
struct Snowflake {
    int x, y;
};

// Количество снежинок
#define NUM_SNOWFLAKES 10
Snowflake snowflakes[NUM_SNOWFLAKES];

// Инициализация снежинок
void initSnowflakes() {
    for (int i = 0; i < NUM_SNOWFLAKES; i++) {
        snowflakes[i].x = random(0, SCREEN_WIDTH);
        snowflakes[i].y = random(0, SCREEN_HEIGHT);
    }
}

// Обновление позиций снежинок
void updateSnowflakes() {
    for (int i = 0; i < NUM_SNOWFLAKES; i++) {
        snowflakes[i].y += random(3, 9); // Увеличенная скорость по оси Y

        // Перезапускаем снежинку сверху, если она упала ниже экрана
        if (snowflakes[i].y >= SCREEN_HEIGHT) {
            snowflakes[i].x = random(0, SCREEN_WIDTH);
            snowflakes[i].y = 0;
        }

        // Отрисовка снежинки
        display.drawPixel(snowflakes[i].x, snowflakes[i].y, SSD1306_WHITE);
    }
}

void drawStroke(int x1, int y1, int x2, int y2) {
    display.drawLine(x1, y1, x2, y2, SSD1306_WHITE);
    display.display();
    delay(100);
}

void displayLogo() {
    display.clearDisplay();

    // Координаты рамки
    const int16_t rectX = 16;
    const int16_t rectY = 16;
    const int16_t rectW = 96;
    const int16_t rectH = 32;

    // Выводим буквы "ESP"
    int startX = rectX + 8, startY = rectY + 4;

    // "E"
    drawStroke(startX, startY, startX + 10, startY);
    drawStroke(startX, startY, startX, startY + 16);
    drawStroke(startX, startY + 8, startX + 8, startY + 8);
    drawStroke(startX, startY + 16, startX + 10, startY + 16);

    startX += 16;

    // "S"
    drawStroke(startX, startY, startX + 10, startY);
    drawStroke(startX, startY, startX, startY + 8);
    drawStroke(startX, startY + 8, startX + 10, startY + 8);
    drawStroke(startX + 10, startY + 8, startX + 10, startY + 16);
    drawStroke(startX, startY + 16, startX + 10, startY + 16);

    startX += 16;

    // "P"
    drawStroke(startX, startY, startX, startY + 16);
    drawStroke(startX, startY, startX + 10, startY);
    drawStroke(startX + 10, startY, startX + 10, startY + 8);
    drawStroke(startX, startY + 8, startX + 10, startY + 8);

    // Рисуем иконку часов
    int clockX = rectX + 64;
    int clockY = rectY + 8;
    display.drawCircle(clockX, clockY + 8, 8, SSD1306_WHITE); // Циферблат
    display.drawLine(clockX, clockY + 8, clockX, clockY, SSD1306_WHITE);    // Часовая стрелка
    display.drawLine(clockX, clockY + 8, clockX + 4, clockY + 8, SSD1306_WHITE);  // Минутная стрелка
    
    // Рамка вокруг надписи и иконки
    display.drawRect(rectX, rectY, rectW, rectH, SSD1306_WHITE);
    display.display();
    delay(2000);
}

void setupAccessPoint() {
    Serial.println("Не удалось подключиться к Wi-Fi, переключаемся в режим точки доступа...");
    WiFi.mode(WIFI_AP);
    WiFi.softAP("ESP_CLOCK", "12345");

    display.clearDisplay();
    display.setCursor(0, 10);
    display.println("AP Mode Active!");
    display.setCursor(0, 20);
    display.print("SSID: ESP_CLOCK");
    display.display();

    server.on("/", []() {
        String html = "<html><head><title>Настройка WiFi</title><style>";
        html += "body { font-family: Arial; background-color: #f9f9f9; }";
        html += "h1 { color: #147efb; }";
        html += "</style></head><body>";
        html += "<h1>Настройка WiFi</h1>";
        html += "<form action=\"/save\" method=\"GET\">";
        html += "SSID: <input type=\"text\" name=\"ssid\"><br>";
        html += "Пароль: <input type=\"text\" name=\"password\"><br>";
        html += "<input type=\"submit\" value=\"Сохранить\">";
        html += "</form>";
        html += "</body></html>";
        server.send(200, "text/html", html);
    });

    server.on("/save", []() {
        if (server.hasArg("ssid") && server.hasArg("password")) {
            ssid = server.arg("ssid");
            password = server.arg("password");
            server.send(200, "text/html", "<html><body><h1>Настройки сохранены. Перезагрузка...</h1></body></html>");
            delay(1000);
            ESP.restart();
        } else {
            server.send(200, "text/html", "<html><body><h1>Ошибка. Введите SSID и Пароль.</h1></body></html>");
        }
    });

    server.begin();
    Serial.println("Сервер запущен в режиме AP");
}

void setup() {
    Serial.begin(115200);

    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);

    pinMode(BUZZER_PIN, OUTPUT);
    digitalWrite(BUZZER_PIN, LOW);

    displayLogo();

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid.c_str(), password.c_str());

    Serial.println("Подключение к WiFi...");

    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
        delay(500);
        Serial.print(".");
        ++attempts;
    }

    if (WiFi.status() != WL_CONNECTED) {
        setupAccessPoint();
    } else {
        Serial.println("WiFi подключено");
        IPAddress localIP = WiFi.localIP();
        Serial.print("IP устройства: ");
        Serial.println(localIP);

        display.clearDisplay();
        display.setCursor(0, 10);
        display.println("WiFi Connected!");
        display.setCursor(0, 20);
        display.print("IP: ");
        display.println(WiFi.localIP());
        display.display();
        delay(2000);

        timeClient.begin();
        Serial.println("NTP клиент запущен");

        displayStart = millis();
    }

    // Инициализируем снежинки
    initSnowflakes();
}

void loop() {
    timeClient.update();
    server.handleClient();

    if (timeClient.getFormattedTime().substring(0, 5) == alarmTime && !alarmActivated) {
        alarmActivated = true;
        for (int i = 0; i < 30000; i += 200) {
            digitalWrite(BUZZER_PIN, HIGH);
            delay(100);
            digitalWrite(BUZZER_PIN, LOW);
            delay(100);
        }
    }

    display.clearDisplay();
    display.setTextSize(2);
    String currentTime = timeClient.getFormattedTime();
    display.setCursor((SCREEN_WIDTH - (currentTime.length() * 12)) / 2, 10);
    display.println(currentTime);

    // Вычислять дату
    time_t rawtime = timeClient.getEpochTime();
    struct tm* timeinfo = localtime(&rawtime);
    char date[11];
    strftime(date, 11, "%d.%m.%Y", timeinfo);
  
    if (millis() - displayStart < 30000) {
        // Показ IP в течение 30 секунд
        display.setTextSize(1);
        String ipAddress = WiFi.localIP().toString();
        display.setCursor((SCREEN_WIDTH - (ipAddress.length() * 6)) / 2, 40);
        display.print("IP: ");
        display.println(ipAddress);
    } else {
        // Показ текущей даты
        display.setTextSize(1);
        display.setCursor((SCREEN_WIDTH - 72) / 2, 40);
        display.println(date);
    }

    // Обновляем и рисуем снежинки
    updateSnowflakes();

    display.display();
    delay(1000);
} и справь скорость обновления снежина на 24 раза в секудну