/*
 * osc.js: An Open Sound Control library for JavaScript that works in both the browser and Node.js
 *
 * Cross-Platform Web Socket client transport for osc.js.
 *
 * Copyright 2014-2016, Colin Clark
 * Licensed under the MIT and GPL 3 licenses.
 */

/*global WebSocket, require*/

var osc = osc || require("../osc.js");

(function () {

    "use strict";

    osc.WebSocket = typeof WebSocket !== "undefined" ? WebSocket : require ("ws");

    osc.WebSocketPort = function (options) {
        osc.Port.call(this, options);
        this.on("open", this.listen.bind(this));

        this.socket = options.socket;
        if (this.socket) {
            if (this.socket.readyState === 1) {
                osc.WebSocketPort.setupSocketForBinary(this.socket);
                this.emit("open", this.socket);
            } else {
                this.open();
            }
        }
    };

    var p = osc.WebSocketPort.prototype = Object.create(osc.Port.prototype);
    p.constructor = osc.WebSocketPort;

    p.open = function () {
        if (!this.socket || this.socket.readyState > 1) {
            this.socket = new osc.WebSocket(this.options.url);
        }

        osc.WebSocketPort.setupSocketForBinary(this.socket);

        var that = this;
        this.socket.onopen = function () {
            that.emit("open", that.socket);
        };

        this.socket.onerror = function (err) {
            that.emit("error", err);
        };
    };

    p.listen = function () {
        var that = this;
        this.socket.onmessage = function (e) {
            that.emit("data", e.data, e);
        };

        this.socket.onclose = function (e) {
            that.emit("close", e);
        };

        that.emit("ready");
    };

    p.sendRaw = function (encoded) {
        if (!this.socket || this.socket.readyState !== 1) {
            osc.fireClosedPortSendError(this);
            return;
        }

        this.socket.send(encoded);
    };

    p.close = function (code, reason) {
        this.socket.close(code, reason);
    };

    osc.WebSocketPort.setupSocketForBinary = function (socket) {
        socket.binaryType = osc.isNode ? "nodebuffer" : "arraybuffer";
    };

}());
