// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma version(1)

#pragma rs java_package_name(com.android.musicvis)

#include "rs_graphics.rsh"

float gYRotation;
int gIdle;
int gWaveCounter;
int gWidth;

rs_program_vertex gPVBackground;
rs_program_fragment gPFBackground;

typedef struct Vertex {
    float2 position;
    float2 texture0;
} Vertex_t;
Vertex_t *gPoints;

rs_allocation gPointBuffer;
rs_allocation gTlinetexture;
rs_mesh gCubeMesh;

#define RSID_POINTS 1

#define FADEOUT_LENGTH 100
#define FADEOUT_FACTOR 0.95f
#define FADEIN_LENGTH 15

static int fadeoutcounter = 0;
static int fadeincounter = 0;
static int wave1pos = 0;
static int wave1amp = 0;
static int wave2pos = 0;
static int wave2amp= 0;
static int wave3pos = 0;
static int wave3amp= 0;
static int wave4pos = 0;
static int wave4amp= 0;
static float idle[8192];
static int waveCounter = 0;

static void makeIdleWave(float *points) {
    // show a number of superimposed moving sinewaves
    float amp1 = sin(0.007f * wave1amp) * 120;
    float amp2 = sin(0.023f * wave2amp) * 80;
    float amp3 = sin(0.011f * wave3amp) * 40;
    float amp4 = sin(0.031f * wave4amp) * 20;
    // calculate how many invisible lines there are on each side
    int skip = (1024 - gWidth) / 2;
    if (skip < 0) skip = 0;
    int end = 1024 - skip;
    for (int i = skip; i < end; i++) {
        float val = sin(0.013f * (wave1pos + i)) * amp1
                  + sin(0.029f * (wave2pos + i)) * amp2;
        float off = sin(0.005f * (wave3pos + i)) * amp3
                  + sin(0.017f * (wave4pos + i)) * amp4;
        if (val < 2.f && val > -2.f) val = 2.f;
        points[i*8+1] = val + off;
        points[i*8+5] = -val + off;
    }
    wave1pos++;
    wave1amp++;
    wave2pos--;
    wave2amp++;
    wave3pos++;
    wave3amp++;
    wave4pos++;
    wave4amp++;
}

int root(int launchID) {
    rsgClearColor(0.f, 0.f, 0.f, 1.f);

    int i;

    // calculate how many invisible lines there are on each side
    int width = gWidth;
    if (width > 1024) width = 1024;
    int skip = (1024 - width) / 2;
    int end = 1024 - skip;

    if (gIdle) {

        // idle state animation
        float *points = (float*)gPoints;
        if (fadeoutcounter > 0) {
            // fade waveform to 0
            for (i = skip; i < end; i++) {
                float val = fabs(points[i*8+1]);
                val = val * FADEOUT_FACTOR;
                if (val < 2.f) val = 2.f;
                points[i*8+1] = val;
                points[i*8+5] = -val;
            }
            fadeoutcounter--;
            if (fadeoutcounter == 0) {
                wave1amp = 0;
                wave2amp = 0;
                wave3amp = 0;
                wave4amp = 0;
            }
        } else {
            // idle animation
            makeIdleWave(points);
        }
        fadeincounter = FADEIN_LENGTH;
    } else {
        if (fadeincounter > 0 && fadeoutcounter == 0) {
            // morph from idle animation back to waveform
            makeIdleWave(idle);
            if (waveCounter != gWaveCounter) {
                waveCounter = gWaveCounter;
                float *points = (float*)gPoints;
                for (i = skip; i < end; i++) {
                    float val = fabs(points[i*8+1]);
                    points[i*8+1] = (val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+1] * fadeincounter) / FADEIN_LENGTH;
                    points[i*8+5] = (-val * (FADEIN_LENGTH - fadeincounter) + idle[i*8+5] * fadeincounter) / FADEIN_LENGTH;
                }
            }
            fadeincounter--;
            if (fadeincounter == 0) {
                fadeoutcounter = FADEOUT_LENGTH;
            }
        } else {
            fadeoutcounter = FADEOUT_LENGTH;
        }
    }

    rs_matrix4x4 mat1;
    float yrot = gYRotation;
    float scale = 0.004165f * (1.0f + 2.f * fabs(sin(radians(yrot))));

    // Draw the visualizer.
    rsgBindProgramVertex(gPVBackground);
    rsgBindProgramFragment(gPFBackground);
    rsgBindTexture(gPFBackground, 0, gTlinetexture);

    // Change the model matrix to account for the large model
    // and to do the necessary rotations.
    rsMatrixLoadIdentity(&mat1);
    rsMatrixRotate(&mat1, yrot, 0.f, 0.f, 1.f);
    rsMatrixScale(&mat1, scale, scale, scale);
    rsgProgramVertexLoadModelMatrix(&mat1);

    rsgDrawMesh(gCubeMesh, 0, skip * 2, width * 2);

    return 1;
}

