import processing.core.*; 
import processing.data.*; 
import processing.event.*; 
import processing.opengl.*; 

import processing.sound.*; 

import java.util.HashMap; 
import java.util.ArrayList; 
import java.io.File; 
import java.io.BufferedReader; 
import java.io.PrintWriter; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.IOException; 

public class AbilityTimer extends PApplet {

// 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.awt.PSurfaceAWT.SmoothCanvas;
//import javax.swing.JFrame;


//final String appname = "Ability Timer";
//final String version = "0.20";

interface GuiItem {
  public void render();
  public void press();
}

PFont font12;
PFont font24;
SoundFile chime;

// true : Timer / false : Memo
boolean timerMode = false;

class TimerDisplay implements GuiItem {
  int x;
  int y;
  int endTime;
  final int itemWidth  = 70;
  final int itemHeight = 30;
  TimerDisplay(int _x, int _y) {
    x       = _x;
    y       = _y;
    endTime = 0;
  }
  public void start(int seconds) {
    endTime = millis() + 1000*seconds;
    timerMode = true;
  }
  public void render() {
    int currentTime = millis();
    int remainTime = endTime - currentTime;
    if (remainTime <= 0) {
      timerMode = false;
      chime.play();
    } else {
      strokeWeight(2); // Fixed a bug of #5
      stroke(128);     // Fixed a bug of #5
      fill(isOver() ? 64 : 0);
      rect(x, y, itemWidth-1, itemHeight-1);
      String msg = "000.0";
      fill(0, 255, 0);
      int sec     = remainTime / 1000;
      int decimal = (remainTime / 100) % 10;
      String zeros = "";
      if (sec < 10) {
        zeros = "00";
      } else if (sec < 100) {
        zeros = "0";
      }
      msg = zeros + str(sec) + "." + str(decimal);
      textFont(font24);
      textSize(24);
      text(msg, x+5, y+22);
    }
  }
  public void press(){
    if(isOver()){
      timerMode = false;
    }
  }
  public boolean isOver(){
    return(x<=mouseX&&mouseX<x+itemWidth && y<=mouseY&&mouseY<y+itemHeight);
  }
}

class TimerBar implements GuiItem {
  int seconds;
  int x, y;
  TimerDisplay td;
  final int itemWidth  =  64;
  final int itemHeight = 310;
  TimerBar(int _seconds, int _x, int _y, TimerDisplay _td){
    seconds = _seconds;
    x  = _x;
    y  = _y;
    td = _td;
  }
  public void render(){
    stroke(224);
    strokeWeight(1);
    fill(255); // Left side
    triangle(x,y+5, x,y+itemHeight, x+itemWidth-1,y+itemHeight-1);
    fill(240); // Right side
    triangle(x,y, x+itemWidth,y,  x+itemWidth-1,y+itemHeight-1);

    if (isOver()) {
      fill(0, 255, 0);
      triangle(x,y, x,mouseY, x+mouseY/5,mouseY);
    }
  }
  public int computeSeconds() {
    int pos = mouseY/2;
    if (pos < 50) {
      // do nothing
    } else {
      pos = 50 + (pos - 50)/4*5;
    }
    return pos;
  }
  public void textRender(){
    if (isOver()) {
      fill(0, 255, 0);
      textFont(font24);
      textSize(24);
      text(str(computeSeconds()) + "sec", x+105, mouseY);
    }
  }
  public void press(){
    if(isOver()){
      td.start(computeSeconds());
    }
  }
  public boolean isOver(){
    return(x<=mouseX&&mouseX<x+itemWidth && y<=mouseY&&mouseY<y+itemHeight);
  }
}

class TimerBarLabel implements GuiItem {
  TimerBar tb;
  TimerBarLabel(TimerBar _tb){
    tb = _tb;
  }
  public void render(){
    if (tb.isOver()) {
      String msg = str(tb.computeSeconds()) + "sec";
      int y = mouseY;
      if (y < 20) {
        y = 20;
      }
      textFont(font24);
      textSize(24);
      fill(64);
      text(msg, tb.x+15+mouseY/5+2, y+2); // shadow
      fill(0, 255, 0);
      text(msg, tb.x+15+mouseY/5, y);
    }
  }
  public void press(){
  }
}

// Thanks to https://forum.processing.org/two/discussion/4849/checkbox
class Checkbox implements GuiItem {
  int x, y;
  boolean b;
  final int itemWidth  = 20;
  final int itemHeight = 20;
  Checkbox(int _x, int _y){
    x = _x;
    y = _y;
    b = false;
  }
  public void render(){
    stroke(0); // color of box's flame
    strokeWeight(1);
    fill(isOver()?224:255); // color of box
    rect(x, y, itemWidth-1, itemHeight-1);
    if(b){
      stroke(255, 0, 0); // color of v
      strokeWeight(2);
      line(x+2, y+10, x+10, y+15);
      line(x+10, y+15, x+17, y+3);
    }
  }
  public void press(){
    if(isOver()){
      b=!b;
    }
  }
  public boolean get(){
    return b;
  }
  public void set(){
    b = true;
  }
  public void reset(){
    b = false;
  }
  public boolean isOver(){
    return(x<=mouseX&&mouseX<x+itemWidth && y<=mouseY&&mouseY<y+itemHeight);
  }
}

int next_y = 5;

class Mission implements GuiItem {
  String name;
  Checkbox[] boxes;
  int y;
  final int delta_y = 29;
  Mission(String _name, int _items){
    name  = _name;
    boxes = new Checkbox[_items];
    y = next_y;
    next_y += delta_y;
    for(int i=0; i< boxes.length; i++){
      boxes[i] = new Checkbox(115 + 25 * i, y);
    }
  }
  public void render(){
    boolean isCurrent = false;
    for(int i=0; i< boxes.length; i++){
      boxes[i].render();
      isCurrent = isCurrent ? true : boxes[i].isOver();
    }
    textFont(font12);
    textSize(12);
    if (isCurrent) {
      fill(128);
      text(name, 5, y+15);
      fill(0);
      text(name, 5-1, y+15-1);
    } else {
      fill(0);
      text(name, 5, y+15);
    }
  }
  public void press(){
    for (int i=0; i< boxes.length; i++) {
      boxes[i].press();

      // Chain reaction
      if (boxes[i].get() == true) {
        for (int j = i-1; j >= 0; j--) {
          boxes[j].set();
        }
      } else {
        for (int j = i+1; j < boxes.length; j++) {
          boxes[j].reset();
        }
      }
    }
  }
  public void release(){
  }
}

ArrayList<GuiItem> timerModeItems = new ArrayList<GuiItem>();
ArrayList<GuiItem> memoModeItems  = new ArrayList<GuiItem>();

//JFrame jframe;

public void setup(){
  
  surface.setAlwaysOnTop(true);
  
  //PSurfaceAWT awtSurface = (PSurfaceAWT) surface;
  //SmoothCanvas smoothCanvas = (SmoothCanvas) awtSurface.getNative();
  //jframe = (JFrame)smoothCanvas.getFrame();
  //jframe.dispose();
  //jframe.setUndecorated(true);
  //jframe.setOpacity(.5f);
  //jframe.setVisible(true);
  
  
  TimerDisplay tmdisp = new TimerDisplay(80, 5);
  timerModeItems.add(tmdisp);

  TimerBar tmbar = new TimerBar(180, 5, 5, tmdisp);
  memoModeItems.add(tmbar);
  font12 = loadFont("mplus-2p-bold-12.vlw");
  font24 = loadFont("mplus-2m-bold-24.vlw");
  chime = new SoundFile(this, "chime.mp3");
  
  Table tbl = loadTable("Items.csv", "header");
  for (TableRow row : tbl.rows()) {
    String kind = row.getString("kind");
    if (kind.equals("mission")) {
      String name  = row.getString("name");
      int    value = row.getInt("value");
      memoModeItems.add(new Mission(name, value));
    }
  }
  memoModeItems.add(new TimerBarLabel(tmbar));
}

public void draw(){
  background(240);
  if (timerMode) {
    for(int i=0; i< timerModeItems.size(); i++){
      timerModeItems.get(i).render();
    }
  } else {
    for(int i=0; i< memoModeItems.size(); i++){
      memoModeItems.get(i).render();
    }
  }
}
 
public void mousePressed(){
  if (timerMode) {
    for(int i=0; i< timerModeItems.size(); i++){
      timerModeItems.get(i).press();
    }
  } else {
    for(int i=0; i< memoModeItems.size(); i++){
      memoModeItems.get(i).press();
    }
  }
}

public void mouseReleased() {
}
  public void settings() {  size(240,320);  smooth(); }
  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "AbilityTimer" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}
