/*
 * Copyright 2008, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "AudioPlugin.h"

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include <string.h>

extern NPNetscapeFuncs*         browser;
extern ANPLogInterfaceV0        gLogI;
extern ANPCanvasInterfaceV0     gCanvasI;
extern ANPPaintInterfaceV0      gPaintI;
extern ANPAudioTrackInterfaceV0 gSoundI;
extern ANPTypefaceInterfaceV0   gTypefaceI;


static void inval(NPP instance) {
    browser->invalidaterect(instance, NULL);
}

static uint16 rnd16(float x, int inset) {
    int ix = (int)roundf(x) + inset;
    if (ix < 0) {
        ix = 0;
    }
    return static_cast<uint16>(ix);
}

static void inval(NPP instance, const ANPRectF& r, bool doAA) {
    const int inset = doAA ? -1 : 0;

    PluginObject *obj = reinterpret_cast<PluginObject*>(instance->pdata);
    NPRect inval;
    inval.left = rnd16(r.left, inset);
    inval.top = rnd16(r.top, inset);
    inval.right = rnd16(r.right, -inset);
    inval.bottom = rnd16(r.bottom, -inset);
    browser->invalidaterect(instance, &inval);
}

static void audioCallback(ANPAudioEvent evt, void* user, ANPAudioBuffer* buffer) {
    switch (evt) {
        case kMoreData_ANPAudioEvent: {
            SoundPlay* play = reinterpret_cast<SoundPlay*>(user);
            size_t amount = fread(buffer->bufferData, 1, buffer->size, play->file);
            buffer->size = amount;
            if (amount == 0) {
                gSoundI.stop(play->track);
                fclose(play->file);
                play->file = NULL;
                // TODO need to notify our main thread to delete the track now
            }

            if (play->fileSize > 0) {
                // TODO we need to properly update the progress value
                play->progress = 1;
                inval(play->instance);
            }


            break;
        }
        default:
            break;
    }
}

///////////////////////////////////////////////////////////////////////////////

AudioPlugin::AudioPlugin(NPP inst) : SubPlugin(inst) {

    const char path[] = "/sdcard/sample.raw";

    // open a file stream
    FILE* f = fopen(path, "r");
    gLogI.log(inst, kDebug_ANPLogType, "--- path %s FILE %p", path, f);

    // setup our private audio struct's default values
    m_soundPlay = new SoundPlay;
    m_soundPlay->instance = inst;
    m_soundPlay->progress = 0;
    m_soundPlay->fileSize = 0;
    m_soundPlay->file = f;
    m_soundPlay->track = NULL;

    // create the audio track
    if (f) {
        m_soundPlay->track = gSoundI.newTrack(44100, kPCM16Bit_ANPSampleFormat, 2, audioCallback, m_soundPlay);
        if (!m_soundPlay->track) {
            fclose(f);
            m_soundPlay->file = NULL;
        }
    }

    // get the audio file's size
    int fileDescriptor = open(path, O_RDONLY);
    struct stat fileStatus;

    if(fileDescriptor <= 0) {
        gLogI.log(inst, kError_ANPLogType, "fopen error");
    }
    else if (fstat(fileDescriptor, &fileStatus) != 0) {
        gLogI.log(inst, kDebug_ANPLogType, "File Size: %d", fileStatus.st_size);
        m_soundPlay->fileSize = fileStatus.st_size;
    } else {
        gLogI.log(inst, kError_ANPLogType, "fstat error");
    }

    // configure the UI elements
    m_activeTouch = false;

    memset(&m_trackRect, 0, sizeof(m_trackRect));
    memset(&m_playRect,  0, sizeof(m_playRect));
    memset(&m_pauseRect, 0, sizeof(m_pauseRect));
    memset(&m_stopRect,  0, sizeof(m_stopRect));

    m_paintTrack = gPaintI.newPaint();
    gPaintI.setFlags(m_paintTrack, gPaintI.getFlags(m_paintTrack) | kAntiAlias_ANPPaintFlag);
    gPaintI.setColor(m_paintTrack, 0xFFC0C0C0);

    m_paintRect = gPaintI.newPaint();
    gPaintI.setFlags(m_paintRect, gPaintI.getFlags(m_paintRect) | kAntiAlias_ANPPaintFlag);
    gPaintI.setColor(m_paintRect, 0xFFA8A8A8);

    m_paintText = gPaintI.newPaint();
    gPaintI.setFlags(m_paintText, gPaintI.getFlags(m_paintText) | kAntiAlias_ANPPaintFlag);
    gPaintI.setColor(m_paintText, 0xFF2F4F4F);
    gPaintI.setTextSize(m_paintText, 18);

    m_paintTrackProgress = gPaintI.newPaint();
    gPaintI.setFlags(m_paintTrackProgress, gPaintI.getFlags(m_paintTrackProgress) | kAntiAlias_ANPPaintFlag);
    gPaintI.setColor(m_paintTrackProgress, 0xFF545454);

    m_paintActiveRect = gPaintI.newPaint();
    gPaintI.setFlags(m_paintActiveRect, gPaintI.getFlags(m_paintActiveRect) | kAntiAlias_ANPPaintFlag);
    gPaintI.setColor(m_paintActiveRect, 0xFF545454);

    ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
    gPaintI.setTypeface(m_paintText, tf);
    gTypefaceI.unref(tf);

    //register for touch events
    ANPEventFlags flags = kTouch_ANPEventFlag;
    NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);
    if (err != NPERR_NO_ERROR) {
        gLogI.log(inst, kError_ANPLogType, "Error selecting input events.");
    }
}

AudioPlugin::~AudioPlugin() {
    gPaintI.deletePaint(m_paintTrack);
    gPaintI.deletePaint(m_paintRect);
    gPaintI.deletePaint(m_paintText);
    gPaintI.deletePaint(m_paintTrackProgress);
    gPaintI.deletePaint(m_paintActiveRect);
    if(m_soundPlay->track)
        gSoundI.deleteTrack(m_soundPlay->track);
    delete m_soundPlay;
}

bool AudioPlugin::supportsDrawingModel(ANPDrawingModel model) {
    return (model == kBitmap_ANPDrawingModel);
}

void AudioPlugin::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) {
    ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);

    ANPRectF clipR;
    clipR.left = clip.left;
    clipR.top = clip.top;
    clipR.right = clip.right;
    clipR.bottom = clip.bottom;
    gCanvasI.clipRect(canvas, &clipR);

    draw(canvas);
    gCanvasI.deleteCanvas(canvas);
}

void AudioPlugin::draw(ANPCanvas* canvas) {
    NPP instance = this->inst();
    PluginObject *obj = (PluginObject*) instance->pdata;

    gLogI.log(instance, kError_ANPLogType, "Drawing");

    const float trackHeight = 30;
    const float buttonWidth = 60;
    const float buttonHeight = 30;
    const int W = obj->window->width;
    const int H = obj->window->height;

    // color the plugin canvas
    gCanvasI.drawColor(canvas, 0xFFCDCDCD);

    // get font metrics
    ANPFontMetrics fontMetrics;
    gPaintI.getFontMetrics(m_paintText, &fontMetrics);

    // draw the track box (1 px from the edge)
    m_trackRect.left = 1;
    m_trackRect.top = 1;
    m_trackRect.right = W - 2;
    m_trackRect.bottom = 1 + trackHeight;
    gCanvasI.drawRect(canvas, &m_trackRect, m_paintTrack);

    // draw the progress bar
    if (m_soundPlay->progress > 0) {
        // TODO need to draw progress bar to cover the proper percentage of the track bar
        gCanvasI.drawRect(canvas, &m_trackRect, m_paintTrackProgress);
    }

    // draw the play box (under track box)
    m_playRect.left = m_trackRect.left + 5;
    m_playRect.top = m_trackRect.bottom + 10;
    m_playRect.right = m_playRect.left + buttonWidth;
    m_playRect.bottom = m_playRect.top + buttonHeight;
    gCanvasI.drawRect(canvas, &m_playRect, getPaint(&m_playRect));
    // draw the play box (under track box)
    const char playText[] = "Play";
    gCanvasI.drawText(canvas, playText, sizeof(playText)-1, m_playRect.left + 5,
                      m_playRect.top - fontMetrics.fTop, m_paintText);

    // draw the pause box (under track box)
    m_pauseRect.left = m_playRect.right + 20;
    m_pauseRect.top = m_trackRect.bottom + 10;
    m_pauseRect.right = m_pauseRect.left + buttonWidth;
    m_pauseRect.bottom = m_pauseRect.top + buttonHeight;
    gCanvasI.drawRect(canvas, &m_pauseRect, getPaint(&m_pauseRect));
    // draw the text in the pause box
    const char pauseText[] = "Pause";
    gCanvasI.drawText(canvas, pauseText, sizeof(pauseText)-1, m_pauseRect.left + 5,
                      m_pauseRect.top - fontMetrics.fTop, m_paintText);

    // draw the stop box (under track box)
    m_stopRect.left = m_pauseRect.right + 20;
    m_stopRect.top = m_trackRect.bottom + 10;
    m_stopRect.right = m_stopRect.left + buttonWidth;
    m_stopRect.bottom = m_stopRect.top + buttonHeight;
    gCanvasI.drawRect(canvas, &m_stopRect, getPaint(&m_stopRect));
    // draw the text in the pause box
    const char stopText[] = "Stop";
    gCanvasI.drawText(canvas, stopText, sizeof(stopText)-1, m_stopRect.left + 5,
                      m_stopRect.top - fontMetrics.fTop, m_paintText);
}

ANPPaint* AudioPlugin::getPaint(ANPRectF* input) {
    return (input == m_activeRect) ? m_paintActiveRect : m_paintRect;
}

int16 AudioPlugin::handleEvent(const ANPEvent* evt) {
    NPP instance = this->inst();

    switch (evt->eventType) {
        case kDraw_ANPEventType:
            switch (evt->data.draw.model) {
                case kBitmap_ANPDrawingModel:
                    drawPlugin(evt->data.draw.data.bitmap, evt->data.draw.clip);
                    return 1;
                default:
                    break;   // unknown drawing model
            }

        case kTouch_ANPEventType: {
            int x = evt->data.touch.x;
            int y = evt->data.touch.y;
            if (kDown_ANPTouchAction == evt->data.touch.action) {

                m_activeTouchRect = validTouch(x,y);
                if(m_activeTouchRect) {
                    m_activeTouch = true;
                    return 1;
                }

            } else if (kUp_ANPTouchAction == evt->data.touch.action && m_activeTouch) {
                handleTouch(x, y);
                m_activeTouch = false;
                return 1;
            } else if (kCancel_ANPTouchAction == evt->data.touch.action) {
                m_activeTouch = false;
            }
            break;
        }
        default:
            break;
    }
    return 0;   // unknown or unhandled event
}

void AudioPlugin::invalActiveRect() {

}

ANPRectF* AudioPlugin::validTouch(int x, int y) {

    if (m_playRect.left && x < m_playRect.right && y > m_playRect.top && y < m_playRect.bottom)
        return &m_playRect;
    else if (m_pauseRect.left && x < m_pauseRect.right && y > m_pauseRect.top && y < m_pauseRect.bottom)
        return &m_pauseRect;
    else if (x > m_stopRect.left && x < m_stopRect.right && y > m_stopRect.top && y < m_stopRect.bottom)
        return &m_stopRect;
    else
        return NULL;
}

void AudioPlugin::handleTouch(int x, int y) {
    NPP instance = this->inst();

    // if the track is null then return
    if (NULL == m_soundPlay->track) {
        gLogI.log(instance, kError_ANPLogType, "---- %p unable to create track",
                  instance);
        return;
    }

    // check to make sure the currentRect matches the activeRect
    ANPRectF* currentRect = validTouch(x,y);
    if (m_activeTouchRect != currentRect)
        return;

    if (currentRect == &m_playRect) {

        gLogI.log(instance, kDebug_ANPLogType, "---- %p starting track (%d)",
                  m_soundPlay->track, gSoundI.isStopped(m_soundPlay->track));

        if (gSoundI.isStopped(m_soundPlay->track)) {
            gSoundI.start(m_soundPlay->track);
        }
    }
    else if (currentRect == &m_pauseRect) {

        gLogI.log(instance, kDebug_ANPLogType, "---- %p pausing track (%d)",
                  m_soundPlay->track, gSoundI.isStopped(m_soundPlay->track));

        if (!gSoundI.isStopped(m_soundPlay->track)) {
            gSoundI.pause(m_soundPlay->track);
        }
    }
    else if (currentRect == &m_stopRect) {

        gLogI.log(instance, kDebug_ANPLogType, "---- %p stopping track (%d)",
                  m_soundPlay->track, gSoundI.isStopped(m_soundPlay->track));

        if (!gSoundI.isStopped(m_soundPlay->track)) {
            gSoundI.stop(m_soundPlay->track);
        }
        if (m_soundPlay->file) {
            fseek(m_soundPlay->file, 0, SEEK_SET);
        }
    }
    else {
        return;
    }

    // set the currentRect to be the activeRect
    m_activeRect = currentRect;
    inval(instance);
}
