import '@int/geotoolkit/bootstrap/polyfill';
import {mergeObjects, init} from '@int/geotoolkit/base';
import {ManipulatorType} from '@int/geotoolkit/seismic/widgets/SeismicViewWidget';
import {CgmPlusExport} from '@int/geotoolkit/seismic/cgmplus/CgmPlusExport';
import {BinaryStream} from '@int/geotoolkit/util/stream/BinaryStream';
import {SegyReader} from '@int/geotoolkit/seismic/data/SegyReader';
import {LocalFile} from '@int/geotoolkit/seismic/data/LocalFile';
import {Reverse} from '@int/geotoolkit/seismic/pipeline/processor/Reverse';
import {AGC} from '@int/geotoolkit/seismic/pipeline/processor/AGC';
import {TaperFilterProcess} from '@int/geotoolkit/seismic/analysis/filters/TaperFilterProcess';
import {NormalizationType} from '@int/geotoolkit/seismic/pipeline/NormalizationType';
import {SeismicPipeline} from '@int/geotoolkit/seismic/pipeline/SeismicPipeline';
import {SeismicColors} from '@int/geotoolkit/seismic/util/SeismicColors';
import {Selection, Events as SelectionEvents} from '@int/geotoolkit/controls/tools/Selection';
import {CrossHair, Events as CrossHairEvents} from '@int/geotoolkit/controls/tools/CrossHair';
import {RubberBand, Events as RubberBandEvents} from '@int/geotoolkit/controls/tools/RubberBand';
import {Alignment as BoxLayoutAlignment} from '@int/geotoolkit/layout/BoxLayout';
import {ColorBarLocation} from '@int/geotoolkit/controls/shapes/ColorBarLocation';
import {SeismicWidget} from '@int/geotoolkit/seismic/widgets/SeismicWidget';
import {Plot} from '@int/geotoolkit/plot/Plot';
import {Magnifier} from './js/magnifier';
import {Range} from '@int/geotoolkit/util/Range';
import {ColorUtil} from '@int/geotoolkit/util/ColorUtil';
import {Group} from '@int/geotoolkit/scene/Group';
import {Paint} from '@int/geotoolkit/controls/tools/Paint';
import {PaintMode} from '@int/geotoolkit/controls/tools/PaintMode';
import {EditEvents} from '@int/geotoolkit/controls/tools/EditEvents';
import {EditMode} from '@int/geotoolkit/controls/tools/EditMode';
import {RenderingSide} from '@int/geotoolkit/seismic/pipeline/RenderingSide';
import {NodeServerDataProvider} from './js/nodeserverdataprovider'; // eslint-disable-line
import {HttpClient} from '@int/geotoolkit/http/HttpClient';
import {RemoteSeismicReader} from '@int/geotoolkit/seismic/data/RemoteSeismicReader';

import './styles/toolbar.css';
import {Toolbar} from '@int/geotoolkit/controls/toolbar/Toolbar';
import {Label} from '@int/geotoolkit/controls/toolbar/Label';
import {AnchorType} from '@int/geotoolkit/util/AnchorType';
import {AutoNumberFormat} from '@int/geotoolkit/util/AutoNumberFormat';
import {RemoteSeismicDataSource} from '@int/geotoolkit/seismic/data/RemoteSeismicDataSource';

import {JSLoader as JSCompression} from '@int/geotoolkit/seismic/data/compression/JSLoader';
import {WasmLoader as WasmCompression} from '@int/geotoolkit/seismic/data/compression/WasmLoader';
import {JSLoader as JSFilters} from '@int/geotoolkit/seismic/analysis/filters/JSLoader';
import {WasmLoader as WasmFilters} from '@int/geotoolkit/seismic/analysis/filters/WasmLoader';

init({
    'imports': [
        JSCompression,
        WasmCompression,
        JSFilters,
        WasmFilters
    ]
});

const MODERN_CSS = [
    '.TableView { ',
    ' fillstyle-color: white;',
    ' header-textstyle-color: white;',
    ' header-textstyle-alignment: center;',
    ' header-headerfillstyle: rgba(95, 151, 217, 1);',
    ' header-gridstyle-color: rgba(95, 151, 217, 1);',
    ' content-evenfillstyle: null;',
    ' content-oddfillstyle: null;',
    ' content-gridstyle-color: transparent;',
    ' index-evenfillstyle: null;',
    ' index-oddfillstyle: null;',
    ' index-gridstyle-color: transparent;',
    ' index-highlightrowfillstyle: rgba(95, 151, 217, 0.5);',
    ' index-activerowfillstyle: rgba(95, 151, 217, 0.5);',

    ' highlightrowfillstyle: rgba(95, 151, 217, 0.5);',
    ' highlightcolumnfillstyle: rgba(95, 151, 217, 0.5);',
    ' activerowfillstyle: rgba(95, 151, 217, 0.5);',
    '}'
].join('\n');

export class SeismicPlot {
    constructor (options) {
        this._magnifier = new Magnifier();

        this._canvas = options['canvas'];
        this._container = options['container'];
        this.warningCallback = options['warningCallback'];
        this.rubberBandZoomEndCallback = options['rubberBandZoomEndCallback'];
        this.doubleClickCallback = options['doubleClickCallback'];
        this.fileOpenedCallback = options['fileOpenedCallback'];
        this.errorCallback = options['errorCallback'];
        this._seismicWidget = null;
        this._annotationOverlay = null;
        this._plot = null;
        this._fileSize = 0;
        this._colorMap = SeismicColors.getDefault().createNamedColorMap('WhiteBlack', 256);
        // this._colorMap = SeismicColors.getDefault().createNamedColorMap("RedWhiteBlack", 256);
    }

    dispose () {
        if (this._magnifier) {
            this._magnifier.dispose();
        }
        if (this._plot) {
            this._plot.dispose();
        }
    }

    resize () {
        if (this._plot != null) {
            this._plot.setSize(this._container.clientWidth, this._container.clientHeight);
        }
    }

    createWidgetFromFile (fileInput) {

        const file = new LocalFile(fileInput);
        this._fileSize = file.fileSize;
        const segyReader = new SegyReader(file);
        segyReader.loadMetaData((reader) => {
            if (reader instanceof Error && this.errorCallback != null) {
                this.errorCallback(reader.message);
                return;
            }
            // this.createRemotePipeline(reader)
            reader.readDataSetStatistics((reader, statistics) => {
                if (reader.getModelLimits().getHeight() === 0 && this.warningCallback != null) {
                    return this.warningCallback();
                }
                return this.createPipelineFromFile(file.getFileName(), reader, statistics);
            });
        });
    }

    createPipelineFromFile (fileName, reader, statistics) {
        const pipeline = new SeismicPipeline(fileName, reader, statistics)
            .setColorMap(this._colorMap)
            .setOptions({
                'normalization': {
                    'type': NormalizationType.RMS,
                    'scale': 0.4
                },
                'plot': {
                    'type': {
                        'Wiggle': false,
                        'InterpolatedDensity': true
                    },
                    'decimationSpacing': 5
                }
            })
            .addTraceProcessor(new TaperFilterProcess({'apply': false, 'name': 'TaperFilter'}))
            .addTraceProcessor(new AGC({'apply': false, 'name': 'AGC'}))
            .addTraceProcessor(new Reverse({'apply': false, 'name': 'Reverse'}));
        this.openPipeline(pipeline);
        this._seismicWidget.setOptions({
            'axes': {
                'samples': {
                    'title': {
                        'visible': true,
                        'text': pipeline.getName()
                    }
                }
            }
        });

    }
  createPipelineFromFile2 (pipeline,fileName, reader, statistics) {
      pipeline.setColorMap(this._colorMap)
      .setOptions({
        'normalization': {
          'type': NormalizationType.RMS,
          'scale': 0.4
        },
        'plot': {
          'type': {
            'Wiggle': false,
            'InterpolatedDensity': true
          },
          'decimationSpacing': 5
        }
      })
      .addTraceProcessor(new TaperFilterProcess({'apply': false, 'name': 'TaperFilter'}))
      .addTraceProcessor(new AGC({'apply': false, 'name': 'AGC'}))
      .addTraceProcessor(new Reverse({'apply': false, 'name': 'Reverse'}));
    this.openPipeline(pipeline);
    this._seismicWidget.setOptions({
      'axes': {
        'samples': {
          'title': {
            'visible': true,
            'text': pipeline.getName()
          }
        }
      }
    });

  }

    createRemotePipeline (reader) {
        const pipeline = new SeismicPipeline('Seismic', reader, reader.getStatistics())
            .setOptions({
                'normalization': {
                    'type': NormalizationType.Limits,
                    'scale': 0.3,
                    'limits': new Range(-15000, 15000)
                },
                'plot': {
                    'type': {
                        'Wiggle': false,
                        'InterpolatedDensity': true
                    },
                    'decimationSpacing': 5
                },
                'colors': {
                    'colorMap': this._colorMap
                }
            })
            .addTraceProcessor(new TaperFilterProcess({'apply': false, 'name': 'TaperFilter'}))
            .addTraceProcessor(new AGC({'apply': true, 'name': 'AGC'}))
            .addTraceProcessor(new Reverse({'apply': false, 'name': 'Reverse'}));
            this.openPipeline(pipeline, {
                'tracescale': 400,
                'samplescale': 2,
                'deviceunit': 'in',
                'sampleunit': 's'
            });
    }

    createSectionQuery (position, key, oppositeKey) {
        if (key.key === 'TraceNumber') {
            // 2D seismic does not need the query
            return {
                'workflow': 'HaarWavelets U',
                'error': 2,
                'agc': true
            };
        }
        const selectKeys = [];
        selectKeys[0] = {
            'name': key['key'],
            'min': position,
            'max': position,
            'step': key['increment'],
            'order': 'asc'
        };
        selectKeys[1] = {
            'name': oppositeKey['key'],
            'min': oppositeKey['min'],
            'max': oppositeKey['max'],
            'step': oppositeKey['increment'],
            'order': 'asc'
        };
        return {
            'workflow': 'HaarWavelets U',
            'error': 2,
            'agc': true,
            'keys': selectKeys,
            'options': null,
            'emptyTracesKey': {
                'name': oppositeKey['key'],
                'min': oppositeKey['min'],
                'max': oppositeKey['max']
            }
        };
    }

    createWidgetFromRemoteFile (host, fileName) {
        const data = new RemoteSeismicDataSource({
            'host': host,
            'file': fileName, // 'data/seismic/WG152D0002-00007A508-PSTM_RAW-FULL_STK-248666312.xgy',
            'version': 2
        });
        data.open(
            () => {
                const keys = data.getKeys();
                const key = keys[0]; // INLINE
                const oppositeKey = keys[1]; // XLINE
                const query = this.createSectionQuery(key['min'], key, oppositeKey);
                data.select(query, (reader) => {
                    this.createRemotePipeline(reader);
                });
            }, (err) => {
                this.warningCallback(err);
            }
        );
    }

    openPipeline (pipeline, scaleOptions) {
        if (pipeline == null) {
            return;
        }
        this._headers = [];
        this._charts = [];
        this._pipeline = pipeline;

        const reader = this._pipeline.getReader();
        const knownHeaders = reader.getTraceHeaderFields();
        let cdpHeader = null;
        knownHeaders.forEach((field) => {
            if (field.getName() === 'CDP') {
                cdpHeader = field;
            }
            this._headers.push({
                'visible': field.getName() === 'CDP',
                'name': field.getName(),
                'color': 'black'
            });
            this._charts.push({
                'visible': field.getName() === 'CDP',
                'name': field.getName(),
                'linestyle': ColorUtil.getRandomColorRgb(true)
            });
        });


        if (cdpHeader == null && this._headers[0]) {
            this._headers[0]['visible'] = true;
            this._charts[0]['visible'] = true;
        }

        if (this._seismicWidget != null) {
            this._seismicWidget.setScaleOptions(scaleOptions || {
                'tracescale': 48
            })
                .setPipeline(this._pipeline)
                .setOptions({
                    'axes': {
                        'headers': {
                            'fields': this._headers
                        }
                    },
                    'auxiliarychart': {
                        'charts': this._charts.filter((chart) => chart['visible'])
                    }
                });

            this._magnifier.setPipeline(this._pipeline);
            return;
        }

        let sampleStatus, valueStatus, traceStatus;
        const autoFormat = new AutoNumberFormat();
        this._plot = new Plot({
            'canvasElement': this._canvas,
            'root': this._seismicWidget = new SeismicWidget(this._pipeline, {
                'layouttype': 'inside',
                'statusbar': {
                    'visible': false,
                    'sections': {
                        'info': function (widget, x, y, sample) {
                            if (sampleStatus == null) return null;
                            let sampleValue = '';
                            let traceNumber = '';
                            let depthValue = '';

                            if (sample) {
                                traceNumber = autoFormat.format(sample['traceNumber'] + 1);
                                if (y != null) {
                                    sampleValue = autoFormat.format(Math.round(sample['sampleValue'] * 10000) / 10000);
                                    depthValue = autoFormat.format(Math.round(sample['location']['y'] * 100) / 100.0);
                                }
                            } else {
                                traceNumber = '';
                                sampleValue = '';
                                depthValue = '';
                            }
                            sampleStatus.setText(' Depth: ' + depthValue);
                            valueStatus.setText(' Value: ' + sampleValue);
                            traceStatus.setText(' Trace: ' + traceNumber);
                            return {
                                'samples': ' Time: ' + depthValue,
                                'value': ' Values: ' + sampleValue,
                                'traces': ' Trace: ' + traceNumber
                            };
                        }
                    }
                },
                'table': {
                    'visible': false,
                    'size': 150,
                    'options': {
                        'tools': {
                            'horizontalscroll': {
                                'type': 'geotoolkit.controls.tools.scroll.HorizontalScroll'
                            },
                            'verticalscroll': {
                                'type': 'geotoolkit.controls.tools.scroll.VerticalScroll'
                            }
                        }
                    }
                },
                'colorbar': {
                    'axis': {
                        'size': 20,
                        'autolabelrotation': true,
                        'tickgenerator': {
                            'edge': {
                                'tickvisible': false,
                                'labelvisible': false
                            }
                        }
                    },
                    'title': {
                        'size': 0
                    },
                    'colorbox': {
                        'size': 10
                    },
                    'location': ColorBarLocation.West,
                    'maxheight': '80%',
                    'alignment': BoxLayoutAlignment.Center
                },
                'axes': {
                    'samples': {
                        'title': {
                            'visible': false
                        }
                    },
                    'headers': {
                        'fields': this._headers,
                        'options': {
                            'minimumSpan': 100
                        }
                    }
                },
                'auxiliarychart': {
                    'size': 120,
                    'visible': false,
                    'title': {
                        'text': 'Auxiliary Chart',
                        'textstyle': {
                            'font': '16px Roboto',
                            'color': 'gray'
                        },
                        'size': 20
                    },
                    'charts': this._charts.filter((chart) => chart['visible'])
                },

                'tools': {
                    'colorbar': {
                        'enabled': true
                    }
                },
                'scroll': {
                    'horizontal': {
                        'type': 'geotoolkit.controls.tools.scroll.HorizontalScroll'
                    },
                    'vertical': {
                        'type': 'geotoolkit.controls.tools.scroll.VerticalScroll'
                    }
                }
            })
        });
        this._seismicWidget.setScaleOptions(scaleOptions || {
            'tracescale': 48
        });

        const statusBar = new Toolbar({
            // custom toolbar styles:
            'size': 30,
            'fontsize': 15,
            'offset': 10,
            'border': '1px solid #A8A8A8',
            'classname': 'cs_status_bar',
            'gap': 0,
            // toolbar buttons list:
            'buttons': [
                sampleStatus = new Label({
                    'text': 'Depth',
                    'title': 'Depth value'
                }).setSize(70, 20),
                '-', // special symbol for gap

                traceStatus = new Label({
                    'padding': 5,
                    'text': 'Trace',
                    'title': 'Trace index'
                }).setSize(90, 20),
                valueStatus = new Label({
                    'padding': 15,
                    'text': 'Value',
                    'title': 'Sample value'
                }).setSize(120, 20)
            ],
            // right-top corner vertical toolbar:
            'orientation': 'horizontal',
            'alignment': AnchorType.RightBottom,
            'tools': this._plot.getTool(),
            'node': this._seismicWidget.getAnnotation('center')
        });

        const manipulatorLayer = this._seismicWidget.getManipulatorLayer();
        this._magnifier.setPipeline(this._pipeline, manipulatorLayer);

        this._seismicWidget.getToolByType(RubberBand)
            .addListener(RubberBandEvents.onZoomEnd, this.rubberBandZoomEndCallback);


        let timerInterval = null;
        this._magnifierCallback = (sender, eventArgs) => {
            const position = eventArgs.getPosition();
            if (Number.isFinite(position.getX()) && Number.isFinite(position.getY())) {
                this.pickFrame(position.getX(), position.getY());
            }
        };
        this._seismicWidget.getToolByType(CrossHair)
            .addListener(CrossHairEvents.onPositionChanged, this._magnifierCallback)
            .addListener(CrossHairEvents.onPositionChanged, (sender, eventArgs) => {
                if (timerInterval != null && isNaN(eventArgs.getPosition().getX()) ) {
                    clearTimeout(timerInterval);
                    timerInterval = null;

                    const plotSceneBounds = this._seismicWidget.getModel().getVisibleDeviceLimits();
                    if (plotSceneBounds.contains(eventArgs.getPlotPoint()) === false) {
                        statusBar.setVisible(false);
                    }
                    return;
                }
                statusBar.setVisible(true);
                statusBar.getElement().style.transition = 'opacity 0s linear 0s';
                statusBar.getElement().style.opacity = 1;


                if (timerInterval != null) {
                    clearTimeout(timerInterval);
                    timerInterval = null;
                }
                timerInterval = setTimeout( () => {
                    clearTimeout(timerInterval);
                    timerInterval = null;

                    statusBar.getElement().style.transition = 'opacity 1s linear 1s';
                    statusBar.getElement().style.opacity = 0;
                }, 200);
            });

        this._seismicWidget.getToolByType(Selection)
            .addListener(SelectionEvents.onDoubleClick, this.doubleClickCallback);

        this.initAnnotationTools();
        this._seismicWidget.setCss(MODERN_CSS);
    }

    fitToBounds () {
        if (this._seismicWidget.getVisibleSeismicModelLimits().getWidth() >= this._seismicWidget.getSeismicModelLimits().getWidth()) {
            const visibleModelLimits = this._seismicWidget.getVisibleSeismicModelLimits()
                .setWidth(this._seismicWidget.getSeismicModelLimits().getWidth());
            this._seismicWidget.setVisibleSeismicModelLimits(visibleModelLimits);
        }
    }

    pickFrame (x, y) {
        if (this._magnifier.getVisible() === true) {
            this._magnifier.pickFrame(x, y);
        }
        return this;
    }

    exportToPDF (settings, visibleLimitsExport) {
        if (!this._seismicWidget) return null;
        const options = mergeObjects(settings, visibleLimitsExport ? {
            'limits': this._seismicWidget.getModel().getVisibleModelLimits()
        } : null);
        this._annotations.setVisible(options.printAnnotations);
        return this._seismicWidget.exportToPdf(options).then(() => {
            this._annotations.setVisible(true);
        });
    }

    getFileSize () {
        return this._fileSize || 0;
    }

    exportToCGM (callback) {
        if (!this._seismicWidget) return;
        this._annotations.setVisible(false);
        const cgmStream = new BinaryStream();
        const exporter = new CgmPlusExport();
        cgmStream.setSaveOptions({'filename': 'seismic_sample.cgm', 'type': 'cgm'});
        exporter.exportToCgmStreamAsync(this._seismicWidget, cgmStream, null, null, null, () => {
            cgmStream.save();
            this._annotations.setVisible(true);
            callback();
        });
    }

    zoomIn () {
        if (this._seismicWidget != null) {
            this._seismicWidget.zoomIn();
            this._annotationTool.update();
        }
    }

    zoomOut () {
        if (this._seismicWidget != null) {
            this._seismicWidget.zoomOut();
            this._annotationTool.update();
        }
    }

    fitToWindow () {
        if (!this._seismicWidget) return;
        this._seismicWidget.fitToBounds();
        this._annotationTool.update();
    }

    setRubberBandZoomEnabled (enabled) {
        if (this._seismicWidget == null) {
            return;
        }
        this._seismicWidget.setManipulatorType(enabled ? ManipulatorType.RubberBand : ManipulatorType.Panning);
    }

    activateMagnifierZoom () {
        if (this._seismicWidget != null) {
            this._magnifier.setVisible(!this._magnifier.getVisible());
        }
    }

    getAnnotationLayer () {
        return this._annotations;
    }

    getAnnotationTool () {
        return this._annotationTool;
    }

    setAnnotationToolMode (mode, icon) {
        if (mode == null) {
            this._annotationTool.setEditMode(EditMode.EditNode);
            this._annotationTool.editNode(null);
            this._annotationTool.setEnabled(false);
        } else {
            const modes = {
                'Draw Polygon': PaintMode.Polygon,
                'Draw Polyline': PaintMode.Polyline,
                'Draw Arrow': PaintMode.Arrow,
                'Draw Callout': PaintMode.Callout,
                'Draw Text': PaintMode.Text,
                'Draw Pencil': PaintMode.Pencil
            };
            mode = modes[mode];
            this._annotationTool.setEnabled(true);
            this._annotationTool.setProperties({
                'editmode': EditMode.Create,
                'mode': mode
            });
            this._annotationTool.getShape()
                .setProperty('icon', icon);
        }
    }

    removeAnnotationTool () {
        if (!this._annotationTool) return;
        if (this._annotationTool.isEnabled() && this._annotationTool.getMode() === PaintMode.Edit &&
            this._annotationTool.getShape() != null) {
            if (Array.isArray(this._annotationTool.getShape())) {
                this._annotationTool.getShape().forEach((shape) => shape.dispose());
            } else {
                this._annotationTool.getShape().dispose();
            }
            this._annotationTool.editNode(null);
        }
    }

    setAuxilaryChartVisible (value) {
        if (this._seismicWidget == null) {
            return;
        }
        this._seismicWidget.setOptions({
            'auxiliarychart': {
                'visible': value === true
            }
        });
    }

    setTraceHeaderTable (value) {
        if (this._seismicWidget == null) {
            return;
        }
        this._seismicWidget.setOptions({
            'table': {
                'visible': value === true
            }
        });
    }

    initAnnotationTools () {
        this._annotations = new Group();
        this._seismicWidget.getOverlayLayer().addChild(this._annotations);

        this._seismicWidget.getTool().insert(0, new Selection()
            .setNodeFilter((nodes) => nodes.filter((node) => this._annotations.indexOfChild(node) >= 0))
            .addListener(SelectionEvents.onPick, (tool, eventArgs) => {
                if (!this._annotationTool.isEnabled()) return;
                const selection = eventArgs.getSelection(),
                    length = selection.length;
                if (length === 0 && this._annotationTool.getMode() === PaintMode.Edit) {
                    this._annotationTool.editNode(null);
                } else if (length > 0 && selection[length - 1] !== this._annotationTool.getShape()) {
                    this._annotationTool.setEditMode(EditMode.EditNode);
                    this._annotationTool.editNode(selection[length - 1]);
                    eventArgs.stopPropagation(true, true);
                }
            }));

        this._seismicWidget.getTool().insert(0, this._annotationTool = new Paint({
            'layer': this._seismicWidget.getManipulatorLayer(),
            'node': {
                'radius': 10,
                'fillstyle': '#c7e1f6',
                'linestyle': {
                    'color': '#0351ad',
                    'width': 2
                }
            },
            'handles': {
                'anchor': {
                    'fillstyle': '#8be73d',
                    'linestyle': '#0351ad'
                }
            }
        }).addListener(EditEvents.Start, (tool, command) => {
            this._annotations.addChild(command.getNode());
        }).addListener(EditEvents.End, (tool, node) => {
            tool.setEditMode(EditMode.EditNode);
            tool.editNode(node);
        })
            .editNode(null)
            .setEnabled(false));
    }

    createServerReader (callback, fileName, errorCallback) {
        const host = 'http://localhost:3002/';
        const data = new RemoteSeismicDataSource({
            'host': host,
            'file': fileName,
            'version': 'node'
        });
        data.open(
            () => {
                data.select({}, (reader) => {
                    callback(reader);
                });
            },
            errorCallback
        );
    }

    switchOnServerRendering (filePath, errorCallback) {
        this.createServerReader((reader) => {
            const pipeline = new SeismicPipeline('Seismic', reader, reader.getStatistics());
            pipeline.setOptions({
                'normalization': {
                    'type': NormalizationType.RMS,
                    'scale': 0.4
                },
                'plot': {
                    'type': {
                        'Wiggle': false,
                        'InterpolatedDensity': true
                    },
                    'decimationSpacing': 5
                },
                'colors': {
                    'colorMap': SeismicColors.getDefault().createNamedColorMap('RedWhiteBlack') // for colorbar
                },
                'renderingside': RenderingSide.Server
            });
            this._seismicWidget.setPipeline(pipeline);
            this._seismicWidget.setOptions({
                'pickingevent': CrossHairEvents.onPointerUp
            });
            this._magnifier.setPipeline(pipeline, this._seismicWidget.getManipulatorLayer());
            this._pipeline = pipeline;
            let fileName = filePath.split('/');
            fileName = fileName[fileName.length - 1];
            this._seismicWidget.setOptions({
                'axes': {
                    'samples': {
                        'title': {
                            'visible': true,
                            'text': fileName
                        }
                    }
                }
            });
        }, filePath, errorCallback);
    }

    switchOffServerRendering () {
        this._seismicWidget.setOptions({
            'pickingevent': CrossHairEvents.onPositionChanged
        });
        this._seismicWidget.getPipeline().setRenderingSide(RenderingSide.Client);
    }

    getInfo () {
        const info = {
            tabs: [{
                tab: 'Info',
                text: 'There is no metadata.'
            }],
            title: 'Information'
        };
        if (this._seismicWidget) {
            const reader = this._seismicWidget.getPipeline().getReader();
            const metadata = reader.getMetaData();
            if (metadata) {
                const ebcdic = metadata.getEBCDICHeader();
                if (ebcdic) {
                    info.tabs = [{
                        tab: 'EBCDIC header',
                        text: ebcdic.map((el) => el.replace(/\+/g, ' ')).join('\n')
                    }];
                }
                const fileName = reader.getSeismicFileName();
                if (fileName) {
                    info.title = 'Information: ' + fileName.substr(fileName.lastIndexOf('/') + 1);
                }
                const binary = metadata.getBinaryHeader();
                if (binary) {
                    info.tabs.push({
                        tab: 'Binary header',
                        text: binary
                    });
                }
                if (reader instanceof RemoteSeismicReader) {
                    const host = reader.getHost();
                    if (host) {
                        info.tabs.push({
                            tab: 'Data source',
                            text: host
                        });
                    }
                }
            }
        }
        return info;
    }

    static checkServer (callback, errorCallback) {
        const url = 'http://localhost:3002/check';
        const httpService = HttpClient.getInstance().getHttp();
        httpService.get(url).then(callback, errorCallback);
    }

    getWidget () {
        return this._seismicWidget;
    }

    getChartNames () {
        return this._charts ? this._charts.map((chart) => chart.name) : [];
    }
}
