// nothing but Aquarium :)
// by: Widyo Rio 
// youtube.com/SkwaDroneSalatiga
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <stdlib.h>

// Definisi untuk OLED SSD1306
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Jumlah ikan dalam akuarium
#define FISH_COUNT 10


// Ukuran ikan
#define FISH_WIDTH 12
#define FISH_HEIGHT 4

// Struktur data untuk ikan
struct Fish {
  int x;       // Posisi X ikan
  int y;       // Posisi Y ikan
  int speed;   // Kecepatan ikan (berapa banyak piksel per gerakan)
  bool direction;  // Arah gerakan (true = ke kanan, false = ke kiri)
  bool besar; // true jika besar false kecil
  int verticalMovement;  // Arah gerakan vertikal (1 = naik, -1 = turun, 0 = diam)
};

// Array untuk menyimpan ikan
Fish fishes[FISH_COUNT];

struct Balon {
  int x; int y;
  int jejari;
  int dx; int dy;
  bool otw;
};

Balon gelembung;

// 'kanan', 12x4px
const unsigned char ikan_kanan [] PROGMEM = {
  0xcf, 0xc0, 0x7f, 0x60, 0x7f, 0xf0, 0xcf, 0xc0
};
// 'kiri', 12x4px
const unsigned char ikan_kiri [] PROGMEM = {
  0x3f, 0x30, 0x6f, 0xe0, 0xff, 0xe0, 0x3f, 0x30
};

// 'kanan', 19x6px
const unsigned char big_kanan [] PROGMEM = {
  0xe0, 0xfe, 0x00, 0x77, 0xab, 0x80, 0x3f, 0x56, 0xc0, 0x3e, 0xae, 0xe0, 0x71, 0xd7, 0xc0, 0xc0, 
  0xff, 0x80
};
// 'kiri', 19x6px
const unsigned char big_kiri [] PROGMEM = {
  0x0f, 0xe0, 0xe0, 0x3a, 0xbd, 0xc0, 0x6d, 0x5f, 0x80, 0xee, 0xaf, 0x80, 0x7d, 0x71, 0xc0, 0x3f, 
  0xe0, 0x60
};

// Fungsi untuk menggambar ikan yang lebih realistis
void drawFish(int x, int y, bool direction, bool ukuran) {
  if (direction) {
    // Gambar ikan menghadap ke kanan
    //display.fillTriangle(x, y, x + FISH_WIDTH, y - FISH_HEIGHT / 2, x + FISH_WIDTH, y + FISH_HEIGHT / 2, SSD1306_WHITE); // Badan ikan
    //display.drawTriangle(x, y, x + FISH_WIDTH, y - FISH_HEIGHT / 2, x + FISH_WIDTH, y + FISH_HEIGHT / 2, SSD1306_WHITE); // Ekor ikan
    if (ukuran) display.drawBitmap(x, y, big_kanan, 19, 6, 1); else display.drawBitmap(x, y, ikan_kanan, 12, 4, 1);
  } else {
    // Gambar ikan menghadap ke kiri
    //display.fillTriangle(x + FISH_WIDTH, y, x, y - FISH_HEIGHT / 2, x, y + FISH_HEIGHT / 2, SSD1306_WHITE); // Badan ikan
    //display.drawTriangle(x + FISH_WIDTH, y, x, y - FISH_HEIGHT / 2, x, y + FISH_HEIGHT / 2, SSD1306_WHITE); // Ekor ikan
    if (ukuran) display.drawBitmap(x, y, big_kiri, 19, 6, 1); else display.drawBitmap(x, y, ikan_kiri, 12, 4, 1);
  }
}

// Fungsi untuk menginisialisasi posisi ikan secara acak
void initializeFish() {
  for (int i = 0; i < FISH_COUNT; i++) {
    fishes[i].x = rand() % (SCREEN_WIDTH - FISH_WIDTH);  // Posisi X acak
    fishes[i].y = rand() % (SCREEN_HEIGHT - FISH_HEIGHT) + 5;  // Posisi Y acak, dengan sedikit margin
    fishes[i].speed = rand() % 3 + 1;  // Kecepatan acak (antara 1 hingga 3 piksel per frame)
    fishes[i].direction = rand() % 2;  // Arah acak (0 = kiri, 1 = kanan)
    fishes[i].besar = rand() % 2; // true besar false kecil
    fishes[i].verticalMovement = 0;     // Awalnya tidak bergerak vertikal
  }
}

// Fungsi untuk menginisialisasi posisi ikan secara acak
void lawanArah() {
  for (int i = 0; i < FISH_COUNT; i++) {
    fishes[i].speed = rand() % 3 + 1;  // Kecepatan acak (antara 1 hingga 3 piksel per frame)
    fishes[i].direction = !fishes[i].direction;
    fishes[i].verticalMovement = (rand() % 2 == 0) ? 1 : -1;  // Tentukan arah (1 = naik, -1 = turun)
  }
}

// Fungsi untuk memperbarui posisi ikan
void updateFish() {
  for (int i = 0; i < FISH_COUNT; i++) {
    // Gerakkan ikan sesuai arah dan kecepatan
    if (fishes[i].direction) {
      fishes[i].x += fishes[i].speed;  // Bergerak ke kanan
      if (fishes[i].x > SCREEN_WIDTH) {
        fishes[i].x = 0;  // Kembali ke kiri jika keluar dari layar
      }
    } else {
      fishes[i].x -= fishes[i].speed;  // Bergerak ke kiri
      if (fishes[i].x < -FISH_WIDTH) {
        fishes[i].x = SCREEN_WIDTH;  // Kembali ke kanan jika keluar dari layar
      }
    }

    // Pergerakan vertikal
    if (rand() % 100 < 5) {  // 5% kemungkinan untuk mengubah arah vertikal
      if (fishes[i].verticalMovement == 0) {
        fishes[i].verticalMovement = (rand() % 2 == 0) ? 1 : -1;  // Tentukan arah (1 = naik, -1 = turun)
      }
    }

    // Update posisi vertikal
    fishes[i].y += fishes[i].verticalMovement;
    
    // Pastikan ikan tidak keluar dari batas layar
    if (fishes[i].y < 0) {
      fishes[i].y = 0;  // Tidak bisa lebih tinggi dari 0
      fishes[i].verticalMovement = 1; // Ubah arah menjadi naik
    } else if (fishes[i].y > SCREEN_HEIGHT - FISH_HEIGHT) {
      fishes[i].y = SCREEN_HEIGHT - FISH_HEIGHT;  // Tidak bisa lebih rendah dari batas bawah
      fishes[i].verticalMovement = -1; // Ubah arah menjadi turun
    }
  }
}

void setup() {
  // Memulai komunikasi I2C dengan OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);  // Jika OLED gagal terhubung, berhenti program
  }

  // Inisialisasi layar OLED
  display.clearDisplay();
  display.display();

  // Inisialisasi posisi dan properti ikan
  initializeFish();
  
  gelembung.otw = false;
}

void loop() {
  // Bersihkan layar
  display.clearDisplay();
  //if (analogRead(A0)>200) lawanArah();
  // Perbarui posisi ikan
  updateFish();

  // Gambar setiap ikan di layar
  for (int i = 0; i < FISH_COUNT; i++) {
    drawFish(fishes[i].x, fishes[i].y, fishes[i].direction,fishes[i].besar) ;
  }

  // proses gelembung
  if (rand() % 100 < 5) {  // 5% kemungkinan untuk muncul gelembung
    if (!gelembung.otw)
    {
     gelembung.x= rand() % SCREEN_WIDTH;
     gelembung.y= SCREEN_HEIGHT;
     gelembung.jejari= 2+rand() % 10; 
     gelembung.dx=-1;
     gelembung.dy= 3+rand() % 3; 
     gelembung.otw= true;
    }
  }
  if (gelembung.otw)
  {
    display.drawCircle(gelembung.x+gelembung.dx, gelembung.y, gelembung.jejari, 1);
    display.drawCircle(gelembung.x+gelembung.dx+gelembung.jejari, gelembung.y+gelembung.dy, gelembung.jejari/2, 1);
    gelembung.y=gelembung.y-gelembung.dy;
    if (gelembung.y<(0-gelembung.jejari)) gelembung.otw=false;
    gelembung.dx=-1*gelembung.dx;    
  }
  // Tampilkan hasil gambar di layar
  display.display();

  // Tambahkan sedikit jeda untuk kecepatan animasi
  delay(100);
}