/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
 */

/* global cordova */

var argscheck = require('cordova/argscheck');
var utils = require('cordova/utils');
var exec = require('cordova/exec');

var mediaObjects = {};

/**
 * This class provides access to the device media, interfaces to both sound and video
 *
 * @constructor
 * @param src                   The file name or url to play
 * @param successCallback       The callback to be called when the file is done playing or recording.
 *                                  successCallback()
 * @param errorCallback         The callback to be called if there is an error.
 *                                  errorCallback(int errorCode) - OPTIONAL
 * @param statusCallback        The callback to be called when media status has changed.
 *                                  statusCallback(int statusCode) - OPTIONAL
 */
var Media = function (src, successCallback, errorCallback, statusCallback) {
    argscheck.checkArgs('sFFF', 'Media', arguments);
    this.id = utils.createUUID();
    mediaObjects[this.id] = this;
    this.src = src;
    this.successCallback = successCallback;
    this.errorCallback = errorCallback;
    this.statusCallback = statusCallback;
    this._duration = -1;
    this._position = -1;
    exec(null, this.errorCallback, 'Media', 'create', [this.id, this.src]);
};

// Media messages
Media.MEDIA_STATE = 1;
Media.MEDIA_DURATION = 2;
Media.MEDIA_POSITION = 3;
Media.MEDIA_ERROR = 9;

// Media states
Media.MEDIA_NONE = 0;
Media.MEDIA_STARTING = 1;
Media.MEDIA_RUNNING = 2;
Media.MEDIA_PAUSED = 3;
Media.MEDIA_STOPPED = 4;
Media.MEDIA_MSG = ['None', 'Starting', 'Running', 'Paused', 'Stopped'];

// "static" function to return existing objs.
Media.get = function (id) {
    return mediaObjects[id];
};

/**
 * Start or resume playing audio file.
 */
Media.prototype.play = function (options) {
    exec(null, null, 'Media', 'startPlayingAudio', [this.id, this.src, options]);
};

/**
 * Stop playing audio file.
 */
Media.prototype.stop = function () {
    var me = this;
    exec(
        function () {
            me._position = 0;
        },
        this.errorCallback,
        'Media',
        'stopPlayingAudio',
        [this.id]
    );
};

/**
 * Seek or jump to a new time in the track..
 */
Media.prototype.seekTo = function (milliseconds) {
    var me = this;
    exec(
        function (p) {
            me._position = p;
        },
        this.errorCallback,
        'Media',
        'seekToAudio',
        [this.id, milliseconds]
    );
};

/**
 * Pause playing audio file.
 */
Media.prototype.pause = function () {
    exec(null, this.errorCallback, 'Media', 'pausePlayingAudio', [this.id]);
};

/**
 * Get duration of an audio file.
 * The duration is only set for audio that is playing, paused or stopped.
 *
 * @return      duration or -1 if not known.
 */
Media.prototype.getDuration = function () {
    return this._duration;
};

/**
 * Get position of audio.
 */
Media.prototype.getCurrentPosition = function (success, fail) {
    var me = this;
    exec(
        function (p) {
            me._position = p;
            success(p);
        },
        fail,
        'Media',
        'getCurrentPositionAudio',
        [this.id]
    );
};

/**
 * Start recording audio file.
 */
Media.prototype.startRecord = function () {
    exec(null, this.errorCallback, 'Media', 'startRecordingAudio', [this.id, this.src]);
};

/**
 * Stop recording audio file.
 */
Media.prototype.stopRecord = function () {
    exec(null, this.errorCallback, 'Media', 'stopRecordingAudio', [this.id]);
};

/**
 * Pause recording audio file.
 */
Media.prototype.pauseRecord = function () {
    exec(null, this.errorCallback, 'Media', 'pauseRecordingAudio', [this.id]);
};

/**
 * Resume recording audio file.
 */
Media.prototype.resumeRecord = function () {
    exec(null, this.errorCallback, 'Media', 'resumeRecordingAudio', [this.id]);
};

/**
 * Release the resources.
 */
Media.prototype.release = function () {
    var me = this;
    exec(
        function () {
            delete mediaObjects[me.id];
        },
        this.errorCallback,
        'Media',
        'release',
        [this.id]
    );
};

/**
 * Adjust the volume.
 */
Media.prototype.setVolume = function (volume) {
    exec(null, null, 'Media', 'setVolume', [this.id, volume]);
};

/**
 * Adjust the playback rate.
 */
Media.prototype.setRate = function (rate) {
    if (cordova.platformId === 'ios') {
        exec(null, null, 'Media', 'setRate', [this.id, rate]);
    } else {
        console.warn('media.setRate method is currently not supported for', cordova.platformId, 'platform.');
    }
};

/**
 * Get amplitude of audio.
 */
Media.prototype.getCurrentAmplitude = function (success, fail) {
    exec(
        function (p) {
            success(p);
        },
        fail,
        'Media',
        'getCurrentAmplitudeAudio',
        [this.id]
    );
};

/**
 * Audio has status update.
 * PRIVATE
 *
 * @param id            The media object id (string)
 * @param msgType       The 'type' of update this is
 * @param value         Use of value is determined by the msgType
 */
Media.onStatus = function (id, msgType, value) {
    var media = mediaObjects[id];

    if (media) {
        switch (msgType) {
        case Media.MEDIA_STATE:
            if (media.statusCallback) {
                media.statusCallback(value);
            }
            if (value === Media.MEDIA_STOPPED) {
                if (media.successCallback) {
                    media.successCallback();
                }
            }
            break;
        case Media.MEDIA_DURATION:
            media._duration = value;
            break;
        case Media.MEDIA_ERROR:
            if (media.errorCallback) {
                media.errorCallback(value);
            }
            break;
        case Media.MEDIA_POSITION:
            media._position = Number(value);
            break;
        default:
            if (console.error) {
                console.error('Unhandled Media.onStatus :: ' + msgType);
            }
            break;
        }
    } else if (console.error) {
        console.error('Received Media.onStatus callback for unknown media :: ' + id);
    }
};

module.exports = Media;

function onMessageFromNative (msg) {
    if (msg.action === 'status') {
        Media.onStatus(msg.status.id, msg.status.msgType, msg.status.value);
    } else {
        throw new Error('Unknown media action' + msg.action);
    }
}

if (cordova.platformId === 'android' || cordova.platformId === 'amazon-fireos' || cordova.platformId === 'windowsphone') {
    var channel = require('cordova/channel');

    channel.createSticky('onMediaPluginReady');
    channel.waitForInitialization('onMediaPluginReady');

    channel.onCordovaReady.subscribe(function () {
        exec(onMessageFromNative, undefined, 'Media', 'messageChannel', []);
        channel.initializationComplete('onMediaPluginReady');
    });
}
