#include <MD_Parola.h>  // Version 3.5.6 zu installieren mittels Bibliotheksmanager 
#include <MD_MAX72xx.h> // Version 3.3.0 zu installieren mittels Bibliotheksmanager 
#include <SPI.h>

// Define the number of devices we have in the chain and the hardware interface
#define MAX_DEVICES 4
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
// Mega2560
#define CS_PIN    53
#define CLK_PIN   52
#define DATA_PIN  51
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

//defining the pins used for each drink, you can changes this depending how you connect the pumps and the drinks.
const byte Vodka = 2;
const byte Cointreau = 3;
const byte CranberryJuice = 4;
const byte Sprite = 5;
const byte LemonJuice = 6;
const byte SugarWater = 7;
const byte BlueCur = 8;
const byte Gin = 9;
const byte Bacardi = 10;
const byte Weinbrand = 11;
const byte Cola = 12;

// how much time there is between switching to the next pump.
int TimeBetweenPours = 500;

void setup()
{
  P.begin();
  Serial.begin(9600);
  Serial.println("The bluetooth gates are open.\n Connect to HC-05 from any other bluetooth device with 1234 as pairing key!");

  // My relayboard is a "low true" board. So setting the output to low energize the relay's. You don't want that they all switch on when powering on the cocktailmaker...
  // Set pin 2-12 to output pins to drive the relay board
  for (byte j = 2; j <= 12; j++)
  {
    digitalWrite(j, HIGH);
    pinMode(j, OUTPUT);
  }
}

void anzeige(const char * text)
{
  //P.displayText(text, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
  P.displayText(text, PA_LEFT, 50, 1000, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}

void loop()
{
  P.displayAnimate();
  static bool zubereitung = false;
  char zeichen = '_';

  if (zubereitung)
  {
    zubereitung = Mix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  } else {
    if (Serial.available() > 0) { // Checks whether data is comming from the serial port
      zeichen = Serial.read(); // Reads the data from the serial port
      Serial.println(zeichen);
    }

    // Cocktails:

    //Vodka sprite
    if (zeichen == 'a') {
      anzeige("Vodka Sprite wird gemacht");
      zubereitung = Mix(3000, 0, 0, 0, 5000, 0, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Blue Lagoon
    if (zeichen == 'b') {
      anzeige("Blue Lagoon wird gemacht");
      zubereitung = Mix(2000, 0, 0, 5000, 1800, 1000, 1800, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }


    // Cosmo
    if (zeichen == 'c') {
      anzeige("Cosmo wird gemacht");
      zubereitung = Mix(2500, 1500, 3800, 0, 1200, 1200, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Lemon drop
    if (zeichen == 'd') {
      anzeige("Lemon drop wird gemacht");
      zubereitung = Mix(1500, 1500, 0, 0, 1800, 1200, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Blue Moon
    if (zeichen == 'e') {
      anzeige("Blue Moon wird gemacht");
      zubereitung = Mix(2000, 0, 3000, 0, 1800, 1200, 1200, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Blue Gin Moon
    if (zeichen == 'f') {
      anzeige("Blue Gin Moon wird gemacht");
      zubereitung = Mix(0, 0, 3000, 0, 1800, 1200, 1200, 2000, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Double Strike
    if (zeichen == 'g') {
      anzeige("Double Strike wird gemacht");
      zubereitung = Mix(2000, 0, 3000, 0, 1800, 0, 1200, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Tom Collins
    if (zeichen == 'h') {
      anzeige("Tom Collins wird gemacht");
      zubereitung = Mix(0, 0, 0, 4000, 1800, 1800, 0, 2200, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Flying Dutchman
    if (zeichen == 'i') {
      anzeige("Flying Dutchman wird gemacht");
      zubereitung = Mix(0, 2000, 0, 0, 1200, 1000, 0, 2000, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // London Cosmo
    if (zeichen == 'j') {
      anzeige("London Cosmo wird gemacht");
      zubereitung = Mix(0, 2000, 5000, 1800, 0, 0, 0, 2000, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }


    // Vodka Cranberry
    if (zeichen == 'k') {
      anzeige("Vodka Cranberry wird gemacht");
      zubereitung = Mix(2000, 0, 5000, 0, 0, 1200, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Cranberry Gin
    if (zeichen == 'l') {
      anzeige("Cranberry Gin wird gemacht");
      zubereitung = Mix(0, 0, 5000, 0, 2000, 0, 0, 2200, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Bacardi Cola
    if (zeichen == 'm') {
      anzeige("Bacardi Cola wird gemacht");
      zubereitung = Mix(0, 0, 0, 0, 0, 0, 0, 0, 1500, 0, 3000); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Weinbrand Cola
    if (zeichen == 'n') {
      anzeige("Weinbrand Cola wird gemacht");
      zubereitung = Mix(0, 0, 0, 0, 0, 0, 0, 0, 0, 1500, 3000); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Testin and maintenance options

    // Set-up Vodka
    if (zeichen == 'o') {
      anzeige("Set-up Vodka");
      zubereitung = Mix(1100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Tripple Sec
    if (zeichen == 'p') {
      anzeige("Set-up Tripple Sec");
      zubereitung = Mix(0, 1100, 0, 0, 0, 0, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Cranberry juice
    if (zeichen == 'q') {
      anzeige("Set-up Cranberry juice");
      zubereitung = Mix(0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Sprite
    if (zeichen == 'r') {
      anzeige("Set-up Sprite");
      zubereitung = Mix(0, 0, 0, 1000, 0, 0, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Lime juice
    if (zeichen == 's') {
      anzeige("Set-up Lime juice");
      zubereitung = Mix(0, 0, 0, 0, 1100, 0, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Sugar water
    if (zeichen == 't') {
      anzeige("Set-up Sugar water");
      zubereitung = Mix(0, 0, 0, 0, 0, 1200, 0, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Blue curacao
    if (zeichen == 'u') {
      anzeige("Set-up Blue curacao");
      zubereitung = Mix(0, 0, 0, 0, 0, 0, 800, 0, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Gin
    if (zeichen == 'v') {
      anzeige("Set-up Gin");
      zubereitung = Mix(0, 0, 0, 0, 0, 0, 0, 1000, 0, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Bacardi
    if (zeichen == 'w') {
      anzeige("Set-up Gin");
      zubereitung = Mix(0, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Weinbrand
    if (zeichen == 'x') {
      anzeige("Set-up Gin");
      zubereitung = Mix(0, 0, 0, 0, 0, 0, 0, 0, 0, 1000, 0); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up Cola
    if (zeichen == 'y') {
      anzeige("Set-up Gin");
      zubereitung = Mix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1000); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }


    // Cleaning
    if (zeichen == 'z') {
      anzeige("Set-up Gin");
      zubereitung = Mix(4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }

    // Set-up all (intial first time after cleaning)
    if (zeichen == '{') {
      anzeige("Set-up All");
      zubereitung = Mix(800, 800, 800, 800, 1000, 1600, 800, 800, 800, 800, 800); // Vodka, Triple Sec, Cranberry juice, Sprite, Lime juice, Sugar water, Blue Curacao, Gin, Bacardi, Weinbrand, Cola
    }
  }
}

bool Mix(const uint16_t TimeVodka, const uint16_t TimeCointreau, const uint16_t TimeCranberryJuice, const uint16_t TimeSprite, const uint16_t TimeLemonJuice, const uint16_t TimeSugarWater, const uint16_t TimeBlueCur, const uint16_t TimeGin, const uint16_t TimeBacardi, const uint16_t TimeWeinbrand, const uint16_t TimeCola ) {
  static uint16_t DelayTimeVodka = 0, DelayTimeCointreau = 0, DelayTimeCranberryJuice = 0, DelayTimeSprite = 0, DelayTimeLemonJuice = 0, DelayTimeSugarWater = 0, DelayTimeBlueCur = 0, DelayTimeGin = 0, DelayTimeBacardi = 0, DelayTimeWeinbrand = 0, DelayTimeCola;
  uint32_t jetzt = millis();
  static uint32_t vorhin = jetzt, intervall = 800;
  static byte schritt = 255;
  if ((TimeVodka + TimeCointreau + TimeCranberryJuice + TimeSprite + TimeLemonJuice + TimeSugarWater + TimeBlueCur + TimeGin + TimeBacardi + TimeWeinbrand + TimeCola) > 0)
  {
    DelayTimeVodka = TimeVodka; DelayTimeCointreau = TimeCointreau; DelayTimeCranberryJuice = TimeCranberryJuice; DelayTimeSprite = TimeSprite; DelayTimeLemonJuice = TimeLemonJuice; DelayTimeSugarWater = TimeSugarWater; DelayTimeBlueCur = TimeBlueCur; DelayTimeGin = TimeGin; DelayTimeBacardi = TimeBacardi; DelayTimeWeinbrand = TimeWeinbrand; DelayTimeCola = TimeCola;
    vorhin = jetzt; intervall = 800; schritt = 0;
  }
  else
  {
    if (jetzt - vorhin >= intervall)
    {
      Serial.print(schritt);
      Serial.print(' ');
      Serial.print(intervall);
      Serial.print('\t');
      switch (schritt)
      {
        case 0:
          intervall = DelayTimeVodka;
          if (intervall > 0)
          {
            digitalWrite(Vodka, LOW);
          }
          break;
        case 1:
          if (intervall > 0)
          {
            digitalWrite(Vodka, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 2:
          intervall = DelayTimeCointreau;
          if (intervall > 0)
          {
            digitalWrite(Cointreau, LOW);
          }
          break;
        case 3:
          if (intervall > 0)
          {
            digitalWrite(Cointreau, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 4:
          intervall = DelayTimeCranberryJuice;
          if (intervall > 0)
          {
            digitalWrite(CranberryJuice, LOW);
          }
          break;
        case 5:
          if (intervall > 0)
          {
            digitalWrite(CranberryJuice, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 6:
          intervall = DelayTimeSprite;
          if (intervall > 0)
          {
            digitalWrite(Sprite, LOW);
          }
          break;
        case 7:
          if (intervall > 0)
          {
            digitalWrite(Sprite, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 8:
          intervall = DelayTimeLemonJuice;
          if (intervall > 0)
          {
            digitalWrite(LemonJuice, LOW);
          }
          break;
        case 9:
          if (intervall > 0)
          {
            digitalWrite(LemonJuice, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 10:
          intervall = DelayTimeSugarWater;
          if (intervall > 0)
          {
            digitalWrite(SugarWater, LOW);
          }
          break;
        case 11:
          if (intervall > 0)
          {
            digitalWrite(SugarWater, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 12:
          intervall = DelayTimeBlueCur;
          if (intervall > 0)
          {
            digitalWrite(BlueCur, LOW);
          }
          break;
        case 13:
          if (intervall > 0)
          {
            digitalWrite(BlueCur, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 14:
          intervall = DelayTimeGin;
          if (intervall > 0)
          {
            digitalWrite(Gin, LOW);
          }
          break;
        case 15:
          if (intervall > 0)
          {
            digitalWrite(Gin, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 16:
          intervall = DelayTimeBacardi;
          if (intervall > 0)
          {
            digitalWrite(Bacardi, LOW);
          }
          break;
        case 17:
          if (intervall > 0)
          {
            digitalWrite(Bacardi, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 18:
          intervall = DelayTimeWeinbrand;
          if (intervall > 0)
          {
            digitalWrite(Weinbrand, LOW);
          }
          break;
        case 19:
          if (intervall > 0)
          {
            digitalWrite(Weinbrand, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 20:
          intervall = DelayTimeCola;
          if (intervall > 0)
          {
            digitalWrite(Cola, LOW);
          }
          break;
        case 21:
          if (intervall > 0)
          {
            digitalWrite(Cola, HIGH);
            intervall = TimeBetweenPours;
          }
          break;

        case 22:
          anzeige("Cocktail ist fertig!");
          Serial.println("fertig");
          schritt = 255;
          return false;
          break;
      }
      vorhin = jetzt;
      schritt++;
    }
  }
  return true;
}