/*
 * 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.
 */

'use strict';

const Util = require('util');
const Errors = require('../Errors');
const IgniteClient = require('../IgniteClient');
const ClientSocket = require('./ClientSocket');
const Logger = require('./Logger');

/** Socket wrapper with failover functionality: reconnects on failure. */
class ClientFailoverSocket {

    constructor(onStateChanged) {
        this._socket = null;
        this._state = IgniteClient.STATE.DISCONNECTED;
        this._onStateChanged = onStateChanged;
    }

    async connect(config) {
        if (this._state !== IgniteClient.STATE.DISCONNECTED) {
            throw new Errors.IllegalStateError();
        }
        this._config = config;
        this._endpointsNumber = this._config._endpoints.length;
        this._endpointIndex = this._getRandomInt(this._endpointsNumber - 1);
        await this._connect();
    }

    async send(opCode, payloadWriter, payloadReader = null) {
        if (this._state !== IgniteClient.STATE.CONNECTED) {
            throw new Errors.IllegalStateError();
        }
        await this._socket.sendRequest(opCode, payloadWriter, payloadReader);
    }

    disconnect() {
        if (this._state !== IgniteClient.STATE.DISCONNECTED) {
            this._changeState(IgniteClient.STATE.DISCONNECTED);
            if (this._socket) {
                this._socket.disconnect();
                this._socket = null;
            }
        }
    }

    async _onSocketDisconnect(error = null) {
        this._changeState(IgniteClient.STATE.CONNECTING, null, error);        
        this._socket = null;
        this._endpointIndex++;
        try {
            await this._connect();
        }
        catch (err) {
        }
    }

    async _connect() {
        const errors = new Array();
        let index, endpoint;
        for (let i = 0; i < this._endpointsNumber; i++) {
            index = (this._endpointIndex + i) % this._endpointsNumber;
            endpoint = this._config._endpoints[index];
            try {
                this._changeState(IgniteClient.STATE.CONNECTING, endpoint);
                this._socket = new ClientSocket(
                    endpoint, this._config, this._onSocketDisconnect.bind(this));
                await this._socket.connect();
                this._changeState(IgniteClient.STATE.CONNECTED, endpoint);
                return;
            }
            catch (err) {
                errors.push(Util.format('[%s] %s', endpoint, err.message));
            }
        }
        const error = errors.join('; ');
        this._changeState(IgniteClient.STATE.DISCONNECTED, endpoint, error);
        this._socket = null;
        throw new Errors.IgniteClientError(error);
    }

    _changeState(state, endpoint = null, reason = null) {
        if (Logger.debug) {
            Logger.logDebug(Util.format('Socket %s: %s -> %s'),
                endpoint ? endpoint : this._socket ? this._socket._endpoint : '',
                this._getState(this._state),
                this._getState(state));
        }
        if (this._state !== state) {
            this._state = state;
            if (this._onStateChanged) {
                this._onStateChanged(state, reason);
            }
        }
    }

    _getState(state) {
        switch (state) {
            case IgniteClient.STATE.DISCONNECTED:
                return 'DISCONNECTED';
            case IgniteClient.STATE.CONNECTING:
                return 'CONNECTING';
            case IgniteClient.STATE.CONNECTED:
                return 'CONNECTED';
            default:
                return 'UNKNOWN';
        }
    }

    // returns a random integer between 0 and max
    _getRandomInt(max) {
        if (max === 0) {
            return 0;
        }
        return Math.floor(Math.random() * (max + 1));
    }
}

module.exports = ClientFailoverSocket;
