// This software is distributed under the terms of the MIT License.
// Copyright (c) 2018, 2019 molelord
// All rights reserved.

import processing.awt.PSurfaceAWT;
import processing.sound.*;

import javax.swing.JFrame;
import java.awt.MouseInfo;
import java.awt.PointerInfo;
import java.awt.Point;

final String AppName       = "AbilityTimer";
final String AppVersion    = "0.63";
final String SaveFileName  = "save.csv";
final String ChimeFileName = "chime.mp3";

ArrayList<GuiItem> timerModeItems     = new ArrayList<GuiItem>();
ArrayList<GuiItem> checklistModeItems = new ArrayList<GuiItem>();
ArrayList<Mission> missions           = new ArrayList<Mission>();

void settings() {
  size(Glbl.W, Glbl.H);
}

void setup(){
  surface.setAlwaysOnTop(true);
  
  PSurfaceAWT.SmoothCanvas smoothCanvas;
  smoothCanvas = (PSurfaceAWT.SmoothCanvas)surface.getNative();
  JFrame jframe;
  jframe = (JFrame)smoothCanvas.getFrame();
  jframe.dispose();
  jframe.setUndecorated(true);
  jframe.setVisible(true);

  surface.setResizable(true);
  
  smooth();

  TimerDisplay tmdisp = new TimerDisplay(20, 5);
  timerModeItems.add(tmdisp);

  CloseButton cbutton_t = new CloseButton(
    Glbl.TimerW-CloseButton.W, 0);
  timerModeItems.add(cbutton_t);

  MinimizeButton mbutton_t = new MinimizeButton(
    Glbl.TimerW-CloseButton.W-MinimizeButton.W, 0);
  timerModeItems.add(mbutton_t);

  TimerBar tmbar = new TimerBar(180, 5, 5, tmdisp);
  checklistModeItems.add(tmbar);

  PFont font12 = loadFont("mplus-2p-bold-12.vlw");
  PFont font24 = loadFont("mplus-2m-bold-24.vlw");
  Glbl.setInstances(surface, jframe, font12, font24,
    new SoundFile(this, ChimeFileName)
  );

  Table chkTbl  = loadTable(SaveFileName, "header");
  Table itemTbl = loadTable("Items.csv", "header");
  ZoneId zoneid = ZoneId.of("America/Los_Angeles");
  int i = 0;
  for (TableRow itemRow : itemTbl.rows()) {
    String kind = itemRow.getString("kind");
    if (kind.equals("mission")) {
      String name  = itemRow.getString("name");
      int    items = itemRow.getInt("value");
      int    value = 0;
      if (chkTbl != null && (i < chkTbl.getRowCount())) {
        TableRow chkRow = chkTbl.getRow(i);
        if (chkRow != null) { 
          value = chkRow.getInt("value");
          i++;
        }
      }
      Mission m = new Mission(name, items, value);
      checklistModeItems.add(m);
      missions.add(m);
    } else if (kind.equals("service")) {
      String name  = itemRow.getString("name");
      if (name.equals("DMM")) {
        zoneid = ZoneId.of("Asia/Tokyo");
      }
    }
  }
  WallClock wallc = new WallClock(zoneid);
  checklistModeItems.add(wallc);
  checklistModeItems.add(new TimerBarLabel(tmbar));

  CloseButton closeb = new CloseButton(
    Glbl.W-CloseButton.W, 0);
  checklistModeItems.add(closeb);

  MinimizeButton minib = new MinimizeButton(
    Glbl.W-CloseButton.W-MinimizeButton.W, 0);
  checklistModeItems.add(minib);

  DrawerButton drawerb = new DrawerButton(
    Glbl.W-DrawerButton.W, Glbl.H/2-DrawerButton.H+7,
    AppName, AppVersion);
  checklistModeItems.add(drawerb);
}

long prevEpochSecond = 0;
int  toggle = 0;

void draw(){
  Glbl.setBgSelected(true);
  
  boolean changed = (Glbl.prevMode != Glbl.mode);
  Glbl.prevMode = Glbl.mode;

  if (Glbl.isTimerMode()) {
    background(224);
    if (changed) {
      Glbl.changeSize();
    }
    for (GuiItem item : timerModeItems) {
      item.render();
    }
  } else {
    boolean mustRedraw = false;
    long currentEpochSecond = Instant.now().getEpochSecond();

    boolean passage0p5sec = false;
    int mil = millis() % 1000;
    if (toggle == 0) {
      if (0 <= mil && mil <= 499) {
        toggle = 1;
        passage0p5sec = true;
      }
    } else {
      if (500 <= mil && mil <= 999) {
        toggle = 0;
        passage0p5sec = true;
      }
    }

    if (mousePressed) {
      mustRedraw = true;
    } else if (pmouseX != mouseX || pmouseY != mouseY) {
      mustRedraw = true;
    } else if (Glbl.isLastOneMinute && currentEpochSecond != prevEpochSecond) {
      mustRedraw = true;
    } else if (Glbl.scouterEnabled && passage0p5sec) {
      mustRedraw = true;
    } else if (currentEpochSecond/60 != prevEpochSecond/60) {
      mustRedraw = true;
    }
    prevEpochSecond = currentEpochSecond;

    if (changed) {
      Glbl.changeSize();
      // Even if true was assigned to mustRedraw here, drawing did not occur.
      // Therefore, by assigning 0 to prevEpochSecond, next draw() will redraw it.
      prevEpochSecond = 0;
    }
    if (mustRedraw) {
      background(224);
      for (GuiItem item : checklistModeItems) {
        item.render();
      }
    }
  }
}
 
int prevMouseX = 0;
int prevMouseY = 0;

void mousePressed(){
  prevMouseX = mouseX;
  prevMouseY = mouseY;
  if (Glbl.isTimerMode()) {
    for (GuiItem item : timerModeItems) {
      item.press();
    }
  } else {
    for (GuiItem item : checklistModeItems) {
      item.press();
    }
  }
}

void mouseReleased() {
}

void mouseDragged() {
  if (Glbl.isBgSelected()) {
    Point mouse = MouseInfo.getPointerInfo().getLocation();
    surface.setLocation(mouse.x - prevMouseX, mouse.y - prevMouseY - 0);
  }
}

void exit() {
  Table tbl = new Table();
  tbl.addColumn("value");
  for (Mission m : missions) {
    TableRow row = tbl.addRow();
    row.setInt("value", m.getValue());
  }
  saveTable(tbl, SaveFileName);
  super.exit();
}
