/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright (c) 2015 Adobe Systems Incorporated. All rights reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */

"use strict";

var MessageDispatcher = require("./MessageDispatcher"),
    Model             = require("./Model"),
    logger            = require("../logger");

var PROTOCOL_VERSION = 1;

/**
 * When a new device is added, this is called to establish the connection.
 */
function connect(device) {
    device.state = Model.DEVICE_STATE.CONNECTING;

    var connectMessage = MessageDispatcher.createMessage({
        messageType: "connect",
        activeDocument: Model.docInfo.current,
        version: PROTOCOL_VERSION,
        authToken: device.id
    });

    MessageDispatcher.sendMessage(connectMessage, device.id);
}

/**
 * If the device refuses a connect message, this handler is called.
 */
function connectionRefusedHandler(message) {
    logger.logMessage("Connection refused" + message, logger.LOGLEVEL_ERROR);
    if (Model.devices.contains(message.sender)) {
        Model.devices.remove(message.sender);
    }
    // TODO analytics logging of connection refused
}

/**
 * When we receive a connect message from the device, this handler is called thus establishing that the
 * connection is up and running.
 */
function connectHandler(message) {
    var deviceId = message.sender,
        device = Model.devices.get(deviceId);

    if (device.state !== Model.DEVICE_STATE.CONNECTING) {
        throw new Error("Received a connect message when the device with the ID " + deviceId + " is " + device.state);
    }

    // Set info first because the change of state will notify listeners of a change to the device
    // and the info should be available at that time.
    device.info = message.payload.deviceInfo;
    if (message.payload.guid) {
        device.guid = message.payload.guid;
    }
    device.state = Model.DEVICE_STATE.CONNECTED;
}

/**
 * Handle a device state change Message
 */
function handleDeviceStateChange(device, oldState, newState) {
    if (newState === Model.DEVICE_STATE.SOCKET_AVAILABLE) {
        connect(device);
    }
}

/**
 * Sets up the listeners for this module.
 */
function init() {
    Model.devices.on(Model.DEVICE_EVENT.STATE_CHANGED, handleDeviceStateChange);
    MessageDispatcher.messages.on(MessageDispatcher.MESSAGE.CONNECTION_REFUSED, connectionRefusedHandler);
    MessageDispatcher.messages.on(MessageDispatcher.MESSAGE.CONNECT, connectHandler);
}

exports.init = init;
