import {implementsInterface} from '@int/geotoolkit/base';
import {HttpClient} from '@int/geotoolkit/http/HttpClient';
import {HttpCancel} from '@int/geotoolkit/http/HttpCancel';
import {Promise} from '@int/geotoolkit/util/Promise';
import {RemoteReaderDataProvider} from '@int/geotoolkit/seismic/data/RemoteReaderDataProvider';
import {IServerSideRenderingProvider} from '@int/geotoolkit/seismic/data/IServerSideRenderingProvider';
import {RemoteReaderDataProviderRegistry} from '@int/geotoolkit/seismic/data/RemoteReaderDataProviderRegistry';
import {ErrorCodes} from '@int/geotoolkit/http/ErrorCodes';
import {obfuscate} from '@int/geotoolkit/lib';
import {log} from '@int/geotoolkit/base';
export class NodeServerDataProvider extends RemoteReaderDataProvider {
    constructor (options) {
        super(options);
        this.options = options;
        this.http = HttpClient.getInstance().getHttp();
        this.token = null;
        this.fileName = '';
    }

    createInstance (options) {
        return new NodeServerDataProvider(options);
    }

    open (fileName) {
        this.fileName = fileName;
        return this.http.get('seismicdata/' + encodeURIComponent(fileName), {
            'responseType': 'json',
            'baseURL': this.options['host']
        }).then((response) => {
            if (response['data'] && response['data']['version']) {
                return response['data'];
            }
            return Promise.reject('Server error');
        }, () => Promise.reject('Cannot connect to the server! Run node server.js!'));
    }

    queryTraces (fileName, query) {
        const token = new HttpCancel();
        return this.http.get('seismicquery/' + encodeURIComponent(fileName), {
            'responseType': 'json',
            'baseURL': this.options['host'],
            'cancel': token
        }).then((response) => {
            if (response['data'] && response['data']['version']) {
                return response['data'];
            }
            return Promise.reject('Server error');
        }, (error) => {
            if (token.isCanceled()) {
                return Promise.reject(error);
            }
            return Promise.reject('Cannot connect to the server! Run node server.js!');
        });
    }

    readTraces (fileName, options) {
        if (options && !Array.isArray(options['traceIndexes'])) {
            options['traceIndexes'] = [];
            for (let i = options['from']; i <= options['to']; ++i) {
                options['traceIndexes'].push(i);
            }
        }
        return this.http.request({
            'url': 'enumeratedtraces',
            'baseURL': this.options['host'],
            'method': 'POST',
            'responseType': 'arraybuffer',
            'headers': {
                'Content-Type': 'application/json'
            },
            'data': {
                'file': fileName,
                'byteOrder': options['byteOrder'],
                'query': options['query'],
                'data': {
                    'byteOrder': options['byteOrder'],
                    'samples': options['samples'] === true,
                    'headers': options['headers'] === true,
                    'traceIndexes': options['traceIndexes']
                }
            },
            'transformResponse': (response) => response['data']
        });
    }

    pickSample (x, y, target, callback) {
        const self = this;
        if (this.token) {
            this.token.cancel();
        }
        this.token = new HttpCancel();
        this.http.get('samples', {
            'responseType': 'json',
            'baseURL': this.options['host'],
            'cancel': self.token,
            'params': {
                'json': JSON.stringify({
                    x: x,
                    y: y,
                    file: this.fileName
                })
            }
        }).then((response) => {
            self.token = null;
            callback.call(target, response['data']);
        }).catch((error) => {
            if (this.token && !this.token.isCanceled() && error.code !== ErrorCodes.Aborted) {
                log(error);
            }
        });
    }
    getTileURLFormatter () {
        return (data) => encodeURI(this.options['host'] + 'seismicimage?json=' + JSON.stringify({
            'width': data['deviceArea'].getWidth(),
            'height': data['deviceArea'].getHeight(),
            'options': data['options'],
            'limits': {
                'starttrace': data['tileRect'].getX(),
                'startsample': data['tileRect'].getY(),
                'traceend': data['tileRect'].getRight(),
                'sampleend': data['tileRect'].getBottom()
            },
            'file': this.fileName
        }));
    }
    getTileLoader () {
        return (data, callback) => {
            const token = new HttpCancel();
            this.http.get(data['url'], {
                'responseType': null,
                'cancel': token
            }).then((response) => {
                if (response['data']) {
                    callback(null, response['data']);
                } else {
                    callback('Server error');
                }
            }).catch((error) => {
                if (!token.isCanceled() && error['code'] !== ErrorCodes.Aborted) {
                    callback(error);
                }
            });
            return token;
        };
    }
}
implementsInterface(NodeServerDataProvider, IServerSideRenderingProvider);
obfuscate(NodeServerDataProvider);
RemoteReaderDataProviderRegistry.getInstance().register('node', new NodeServerDataProvider());
