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

import moonlander.library.*; 
import ddf.minim.*; 

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 onescene extends PApplet {

// Import external functions here:

// Moonlander is a library for integrating Processing with Rocket
// Rocket is a tool for synchronizing music and visuals in demoscene projects.

// Minim is needed for the music playback.


// Global variables

// These control how big the opened window is.
final int CANVAS_WIDTH = 1920; // We want 1920 pixels wide...
final int CANVAS_HEIGHT = 1080; // and 1080 pixels tall canvas to get FullHD aka 1080p.

final int FPS = 60; // We want  to run in 60 FPS for broadcast reasons

float ASPECT_RATIO = (float)CANVAS_WIDTH/CANVAS_HEIGHT;  // Aspect ratio of the canvas

float time = 0.0f; // Time in seconds from Moonlander / GNURocket

Moonlander moonlander; // Moonlander instance

// Needed for audio
Minim minim;

PShader shader;
PShader glitch;

PFont font;

String tag = "eimink 2021";

// Array for storing texts we want to display
String[] texts = {
  "Hello Assembly Winter 2021!",
  "It sucks that we can't meet face to face",
  "but at least we can still party online!",
  "Hope you like the compos and other content",
  "and don't forget to vote!",
  ">>> scene.assembly.org <<<",
  "Greetings fly out to",
  "Wide Load",
  "Paraguay",
  "Jumalauta",
  "Byterapers",
  "Adapt",
  "Accession",
  "and YOU!"
};

// Now lets setup audio playing
public void setupAudio() {
  minim = new Minim(this);
}


public void settings() {
  boolean fullscreen = true;
  String renderer = P3D; // Renderer to use either P2D,P3D or JAVA2D.
  if (fullscreen) {
    // Set the window fullscreen in desktop's native resolution
    fullScreen(renderer);
  }
  else {
    // Open as window
    size(CANVAS_WIDTH, CANVAS_HEIGHT, renderer);
  }
  
}

public void setup() {
  shader = loadShader("shader.glsl");
  glitch = loadShader("glitch.glsl");
  shader.set("iResolution",(float)CANVAS_WIDTH,(float)CANVAS_HEIGHT);
  glitch.set("iResolution",(float)CANVAS_WIDTH,(float)CANVAS_HEIGHT);
  
  // Load the font
  // NOTE: You can use system available fonts like "MS Comic Sans" but that usually makes your production less cross-platform
  //       hence we'd recommend to save the font as an asset to the production.
  //       Just remember that font creators have copyrights, so the license needs to be appropriate to use in a demo.
  
  font = createFont("freshmarker.ttf", 200);
 
  //hide mouse cursor
  noCursor();

  // Init & start moonlander
  int bpm = 120; // Tune's beats per minute
  int rowsPerBeat = 4; // How many rows one beat consists of in the sync editor (Rocket or so)
  moonlander = Moonlander.initWithSoundtrack(this, "303-909.mp3", bpm, rowsPerBeat);
  moonlander.start();
  frameRate(FPS); // Set the frame rate
  
}

/*
 * Draw mesages and greetings texts
 */
public void drawText() {
  if (moonlander.getValue("font:text") >= 0) {
    pushMatrix();
    shader(glitch);
    glitch.set("iTime",time);
    glitch.set("alpha",(float)moonlander.getValue("font:a"));
    scale((float)moonlander.getValue("font:scale"));
    textAlign(CENTER, CENTER);
    textFont(font);
    rotateX(sin(time));
    rotateY(cos(time));
    rotateZ(sin(time));
    fill((int)(moonlander.getValue("font:r") * 255),(int)(moonlander.getValue("font:g") * 255),(int)(moonlander.getValue("font:b") * 255),(int)(moonlander.getValue("font:a") * 255));
    text(texts[(int)moonlander.getValue("font:text")%texts.length], (int)moonlander.getValue("font:x"), (int)moonlander.getValue("font:y"));
    resetShader();
    text(texts[(int)moonlander.getValue("font:text")%texts.length], (int)moonlander.getValue("font:x"), (int)moonlander.getValue("font:y"));
    popMatrix();
    
  }
}

public void drawTagText() {
    pushMatrix();
    shader(glitch);
    glitch.set("iTime",time);
    glitch.set("alpha",(float)moonlander.getValue("tag:a"));
    scale((float)moonlander.getValue("tag:scale"));
    textAlign(CENTER, CENTER);
    textFont(font);
    rotateX((float)moonlander.getValue("tag:rx"));
    rotateY((float)moonlander.getValue("tag:ry"));
    rotateZ((float)moonlander.getValue("tag:rz"));
    fill((int)(moonlander.getValue("tag:r") * 255),(int)(moonlander.getValue("tag:g") * 255),(int)(moonlander.getValue("tag:b") * 255),(int)(moonlander.getValue("tag:a") * 255));
    text(tag, (int)moonlander.getValue("tag:x"), (int)moonlander.getValue("tag:y"));
    resetShader();
    text(tag, (int)moonlander.getValue("tag:x"), (int)moonlander.getValue("tag:y"));
    popMatrix();
}

/*
 * This function is called every time a screen is drawn, ideally that would be 60 times per second
 */
public void draw() {
  // update Rocket sync data  
  moonlander.update();

  time = (float)moonlander.getCurrentTime();
  float end = 60.0f; //end production after 60 secs which is the maximum time allowed by the One Scene Compo
  if (time > end) {
    exit();
  }
    
  // Set the background color
  background((int)(moonlander.getValue("bg:r") * 255),(int)(moonlander.getValue("bg:g") * 255),(int)(moonlander.getValue("bg:b") * 255),(int)(moonlander.getValue("bg:a") * 255));
  
  shader(shader);
  shader.set("iTime",time);
  shader.set("scaler",(float)moonlander.getValue("shader:scaler"));
  rect(0,0,width,height);
  resetShader();
  
  /*
   * Center coordinates to screen and make the window and canvas resolution independent
   * This is because actual window in full screen on a 4K monitor has more pixels than FullHD resolution
   * so scaling is needed to ensure that all objects (3D and 2D) are in correct places regardless of the desktop resolution
   */
  translate(width/2, height/2, 0);
  scale(width/CANVAS_WIDTH,height/CANVAS_HEIGHT,width/CANVAS_WIDTH);

  // Enable lights and depth testing to ensure that 3D meshes are drawn in correct order
  lights();
  hint(ENABLE_DEPTH_TEST);

  // disable lights and depth testing so that 2D overlays and text can be draw on top of 3D
  noLights();
  hint(DISABLE_DEPTH_TEST);

  drawText();
  drawTagText();

}

// Handle keypresses
public void keyPressed() {
  if (key == CODED) {
    // if ESC was pressed we exit from demo. 
    // This is a requirement in Assembly compo rules for desktop platforms.
    if (keyCode == ESC) {
      exit();
    }
  }
}
  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "onescene" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}
