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

import _ from 'lodash';
import {nonEmpty, nonNil} from 'app/utils/lodashMixins';
import id8 from 'app/utils/id8';
import {timer, merge, defer, of, EMPTY} from 'rxjs';
import {tap, switchMap, exhaustMap, take, pluck, distinctUntilChanged, filter, map, catchError} from 'rxjs/operators';

import {CSV} from 'app/services/CSV';

import paragraphRateTemplateUrl from 'views/sql/paragraph-rate.tpl.pug';
import cacheMetadataTemplateUrl from 'views/sql/cache-metadata.tpl.pug';
import chartSettingsTemplateUrl from 'views/sql/chart-settings.tpl.pug';
import messageTemplateUrl from 'views/templates/message.tpl.pug';

import {default as Notebook} from '../../notebook.service';
import {default as MessagesServiceFactory} from 'app/services/Messages.service';
import {default as LegacyConfirmServiceFactory} from 'app/services/Confirm.service';
import {default as InputDialog} from 'app/components/input-dialog/input-dialog.service';
import {QueryActions} from './components/query-actions-button/controller';

// Time line X axis descriptor.
const TIME_LINE = {value: -1, type: 'java.sql.Date', label: 'TIME_LINE'};

// Row index X axis descriptor.
const ROW_IDX = {value: -2, type: 'java.lang.Integer', label: 'ROW_IDX'};

const NON_COLLOCATED_JOINS_SINCE = '1.7.0';

const COLLOCATED_QUERY_SINCE = [['2.3.5', '2.4.0'], ['2.4.6', '2.5.0'], ['2.5.1-p13', '2.6.0'], '2.7.0'];

const ENFORCE_JOIN_SINCE = [['1.7.9', '1.8.0'], ['1.8.4', '1.9.0'], '1.9.1'];

const LAZY_QUERY_SINCE = [['2.1.4-p1', '2.2.0'], '2.2.1'];

const DDL_SINCE = [['2.1.6', '2.2.0'], '2.3.0'];

const _fullColName = (col) => {
    const res = [];

    if (col.schemaName)
        res.push(col.schemaName);

    if (col.typeName)
        res.push(col.typeName);

    res.push(col.fieldName);

    return res.join('.');
};

let paragraphId = 0;

class Paragraph {
    name: string;
    qryType: 'scan' | 'query';

    constructor($animate, $timeout, JavaTypes, errorParser, paragraph) {
        const self = this;

        self.id = 'paragraph-' + paragraphId++;
        self.qryType = paragraph.qryType || 'query';
        self.maxPages = 0;
        self.filter = '';
        self.useAsDefaultSchema = false;
        self.localQueryMode = false;
        self.csvIsPreparing = false;
        self.scanningInProgress = false;

        _.assign(this, paragraph);

        Object.defineProperty(this, 'gridOptions', {value: {
            enableGridMenu: false,
            enableColumnMenus: false,
            flatEntityAccess: true,
            fastWatch: true,
            categories: [],
            rebuildColumns() {
                if (_.isNil(this.api))
                    return;

                this.categories.length = 0;

                this.columnDefs = _.reduce(self.meta, (cols, col, idx) => {
                    cols.push({
                        displayName: col.fieldName,
                        headerTooltip: _fullColName(col),
                        field: idx.toString(),
                        minWidth: 50,
                        cellClass: 'cell-left',
                        visible: self.columnFilter(col)
                    });

                    this.categories.push({
                        name: col.fieldName,
                        visible: self.columnFilter(col),
                        enableHiding: true
                    });

                    return cols;
                }, []);

                $timeout(() => this.api.core.notifyDataChange('column'));
            },
            adjustHeight() {
                if (_.isNil(this.api))
                    return;

                this.data = self.rows;

                const height = Math.min(self.rows.length, 15) * 30 + 47;

                // Remove header height.
                this.api.grid.element.css('height', height + 'px');

                $timeout(() => this.api.core.handleWindowResize());
            },
            onRegisterApi(api) {
                $animate.enabled(api.grid.element, false);

                this.api = api;

                this.rebuildColumns();

                this.adjustHeight();
            }
        }});

        Object.defineProperty(this, 'chartHistory', {value: []});

        Object.defineProperty(this, 'error', {value: {
            root: {},
            message: ''
        }});

        this.setError = (err) => {
            this.error.root = err;
            this.error.message = errorParser.extractMessage(err);

            let cause = err;

            while (nonNil(cause)) {
                if (nonEmpty(cause.className) &&
                    _.includes(['SQLException', 'JdbcSQLException', 'QueryCancelledException'], JavaTypes.shortClassName(cause.className))) {
                    this.error.message = errorParser.extractMessage(cause.message || cause.className);

                    break;
                }

                cause = cause.cause;
            }

            if (_.isEmpty(this.error.message) && nonEmpty(err.className)) {
                this.error.message = 'Internal cluster error';

                if (nonEmpty(err.className))
                    this.error.message += ': ' + err.className;
            }
        };
    }

    resultType() {
        if (_.isNil(this.queryArgs))
            return null;

        if (nonEmpty(this.error.message))
            return 'error';

        if (_.isEmpty(this.rows))
            return 'empty';

        return this.result === 'table' ? 'table' : 'chart';
    }

    nonRefresh() {
        return _.isNil(this.rate) || _.isNil(this.rate.stopTime);
    }

    table() {
        return this.result === 'table';
    }

    chart() {
        return this.result !== 'table' && this.result !== 'none';
    }

    nonEmpty() {
        return this.rows && this.rows.length > 0;
    }

    queryExecuted() {
        return nonEmpty(this.meta) || nonEmpty(this.error.message);
    }

    scanExplain() {
        return this.queryExecuted() && this.queryArgs.type !== 'QUERY';
    }

    timeLineSupported() {
        return this.result !== 'pie';
    }

    chartColumnsConfigured() {
        return nonEmpty(this.chartKeyCols) && nonEmpty(this.chartValCols);
    }

    chartTimeLineEnabled() {
        return nonEmpty(this.chartKeyCols) && _.eq(this.chartKeyCols[0], TIME_LINE);
    }

    executionInProgress(showLocal = false) {
        return this.loading && (this.localQueryMode === showLocal);
    }

    checkScanInProgress(showLocal = false) {
        return this.scanningInProgress && (this.localQueryMode === showLocal);
    }

    cancelRefresh($interval) {
        if (this.rate && this.rate.stopTime) {
            $interval.cancel(this.rate.stopTime);

            delete this.rate.stopTime;
        }
    }

    reset($interval) {
        this.meta = [];
        this.chartColumns = [];
        this.chartKeyCols = [];
        this.chartValCols = [];
        this.error.root = {};
        this.error.message = '';
        this.rows = [];
        this.duration = 0;

        this.cancelRefresh($interval);
    }
}

// Controller for SQL notebook screen.
export class NotebookCtrl {
    static $inject = ['IgniteInput', '$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$filter', '$modal', '$popover', '$window', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'AgentManager', 'IgniteChartColors', 'IgniteNotebook', 'IgniteNodes', 'uiGridExporterConstants', 'IgniteVersion', 'IgniteActivitiesData', 'JavaTypes', 'IgniteCopyToClipboard', 'CSV', 'IgniteErrorParser', 'DemoInfo'];

    /**
     * @param {CSV} CSV
     */
    constructor(private IgniteInput: InputDialog, $root, private $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $filter, $modal, $popover, $window, Loading, LegacyUtils, private Messages: ReturnType<typeof MessagesServiceFactory>, private Confirm: ReturnType<typeof LegacyConfirmServiceFactory>, agentMgr, IgniteChartColors, private Notebook: Notebook, Nodes, uiGridExporterConstants, Version, ActivitiesData, JavaTypes, IgniteCopyToClipboard, CSV, errorParser, DemoInfo) {
        const $ctrl = this;

        this.CSV = CSV;
        Object.assign(this, { $root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $filter, $modal, $popover, $window, Loading, LegacyUtils, Messages, Confirm, agentMgr, IgniteChartColors, Notebook, Nodes, uiGridExporterConstants, Version, ActivitiesData, JavaTypes, errorParser, DemoInfo });

        // Define template urls.
        $ctrl.paragraphRateTemplateUrl = paragraphRateTemplateUrl;
        $ctrl.cacheMetadataTemplateUrl = cacheMetadataTemplateUrl;
        $ctrl.chartSettingsTemplateUrl = chartSettingsTemplateUrl;
        $ctrl.demoStarted = false;

        this.isDemo = $root.IgniteDemoMode;

        const _tryStopRefresh = function(paragraph) {
            paragraph.cancelRefresh($interval);
        };

        const _stopTopologyRefresh = () => {
            if ($scope.notebook && $scope.notebook.paragraphs)
                $scope.notebook.paragraphs.forEach((paragraph) => _tryStopRefresh(paragraph));
        };

        $scope.$on('$stateChangeStart', _stopTopologyRefresh);

        $scope.caches = [];

        $scope.pageSizesOptions = [
            {value: 50, label: '50'},
            {value: 100, label: '100'},
            {value: 200, label: '200'},
            {value: 400, label: '400'},
            {value: 800, label: '800'},
            {value: 1000, label: '1000'}
        ];

        $scope.maxPages = [
            {label: 'Unlimited', value: 0},
            {label: '1', value: 1},
            {label: '5', value: 5},
            {label: '10', value: 10},
            {label: '20', value: 20},
            {label: '50', value: 50},
            {label: '100', value: 100}
        ];

        $scope.timeLineSpans = ['1', '5', '10', '15', '30'];

        $scope.aggregateFxs = ['FIRST', 'LAST', 'MIN', 'MAX', 'SUM', 'AVG', 'COUNT'];

        $scope.modes = LegacyUtils.mkOptions(['PARTITIONED', 'REPLICATED', 'LOCAL']);

        $scope.loadingText = $root.IgniteDemoMode ? 'Demo grid is starting. Please wait...' : 'Loading query notebook screen...';

        $scope.timeUnit = [
            {value: 1000, label: 'seconds', short: 's'},
            {value: 60000, label: 'minutes', short: 'm'},
            {value: 3600000, label: 'hours', short: 'h'}
        ];

        $scope.metadata = [];

        $scope.metaFilter = '';

        $scope.metaOptions = {
            nodeChildren: 'children',
            dirSelectable: true,
            injectClasses: {
                iExpanded: 'fa fa-minus-square-o',
                iCollapsed: 'fa fa-plus-square-o'
            }
        };

        const maskCacheName = $filter('defaultName');

        // We need max 1800 items to hold history for 30 mins in case of refresh every second.
        const HISTORY_LENGTH = 1800;

        const MAX_VAL_COLS = IgniteChartColors.length;

        $anchorScroll.yOffset = 55;

        $scope.chartColor = function(index) {
            return {color: 'white', 'background-color': IgniteChartColors[index]};
        };

        function _chartNumber(arr, idx, dflt) {
            if (idx >= 0 && arr && arr.length > idx && _.isNumber(arr[idx]))
                return arr[idx];

            return dflt;
        }

        function _min(rows, idx, dflt) {
            let min = _chartNumber(rows[0], idx, dflt);

            _.forEach(rows, (row) => {
                const v = _chartNumber(row, idx, dflt);

                if (v < min)
                    min = v;
            });

            return min;
        }

        function _max(rows, idx, dflt) {
            let max = _chartNumber(rows[0], idx, dflt);

            _.forEach(rows, (row) => {
                const v = _chartNumber(row, idx, dflt);

                if (v > max)
                    max = v;
            });

            return max;
        }

        function _sum(rows, idx) {
            let sum = 0;

            _.forEach(rows, (row) => sum += _chartNumber(row, idx, 0));

            return sum;
        }

        function _aggregate(rows, aggFx, idx, dflt) {
            const len = rows.length;

            switch (aggFx) {
                case 'FIRST':
                    return _chartNumber(rows[0], idx, dflt);

                case 'LAST':
                    return _chartNumber(rows[len - 1], idx, dflt);

                case 'MIN':
                    return _min(rows, idx, dflt);

                case 'MAX':
                    return _max(rows, idx, dflt);

                case 'SUM':
                    return _sum(rows, idx);

                case 'AVG':
                    return len > 0 ? _sum(rows, idx) / len : 0;

                case 'COUNT':
                    return len;

                default:
            }

            return 0;
        }

        function _chartLabel(arr, idx, dflt) {
            if (arr && arr.length > idx && _.isString(arr[idx]))
                return arr[idx];

            return dflt;
        }

        function _chartDatum(paragraph) {
            let datum = [];

            if (paragraph.chartColumnsConfigured()) {
                paragraph.chartValCols.forEach(function(valCol) {
                    let index = 0;
                    let values = [];
                    const colIdx = valCol.value;

                    if (paragraph.chartTimeLineEnabled()) {
                        const aggFx = valCol.aggFx;
                        const colLbl = valCol.label + ' [' + aggFx + ']';

                        if (paragraph.charts && paragraph.charts.length === 1)
                            datum = paragraph.charts[0].data;

                        const chartData = _.find(datum, {series: valCol.label});

                        const leftBound = new Date();
                        leftBound.setMinutes(leftBound.getMinutes() - parseInt(paragraph.timeLineSpan, 10));

                        if (chartData) {
                            const lastItem = _.last(paragraph.chartHistory);

                            values = chartData.values;

                            values.push({
                                x: lastItem.tm,
                                y: _aggregate(lastItem.rows, aggFx, colIdx, index++)
                            });

                            while (values.length > 0 && values[0].x < leftBound)
                                values.shift();
                        }
                        else {
                            _.forEach(paragraph.chartHistory, (history) => {
                                if (history.tm >= leftBound) {
                                    values.push({
                                        x: history.tm,
                                        y: _aggregate(history.rows, aggFx, colIdx, index++)
                                    });
                                }
                            });

                            datum.push({series: valCol.label, key: colLbl, values});
                        }
                    }
                    else {
                        index = paragraph.total;

                        values = _.map(paragraph.rows, function(row) {
                            const xCol = paragraph.chartKeyCols[0].value;

                            const v = {
                                x: _chartNumber(row, xCol, index),
                                xLbl: _chartLabel(row, xCol, null),
                                y: _chartNumber(row, colIdx, index)
                            };

                            index++;

                            return v;
                        });

                        datum.push({series: valCol.label, key: valCol.label, values});
                    }
                });
            }

            return datum;
        }

        function _xX(d) {
            return d.x;
        }

        function _yY(d) {
            return d.y;
        }

        function _xAxisTimeFormat(d) {
            return d3.time.format('%X')(new Date(d));
        }

        const _intClasses = ['java.lang.Byte', 'java.lang.Integer', 'java.lang.Long', 'java.lang.Short'];

        function _intType(cls) {
            return _.includes(_intClasses, cls);
        }

        const _xAxisWithLabelFormat = function(paragraph) {
            return function(d) {
                const values = paragraph.charts[0].data[0].values;

                const fmt = _intType(paragraph.chartKeyCols[0].type) ? 'd' : ',.2f';

                const dx = values[d];

                if (!dx)
                    return d3.format(fmt)(d);

                const lbl = dx.xLbl;

                return lbl ? lbl : d3.format(fmt)(d);
            };
        };

        function _xAxisLabel(paragraph) {
            return _.isEmpty(paragraph.chartKeyCols) ? 'X' : paragraph.chartKeyCols[0].label;
        }

        const _yAxisFormat = function(d) {
            const fmt = d < 1000 ? ',.2f' : '.3s';

            return d3.format(fmt)(d);
        };

        function _updateCharts(paragraph) {
            $timeout(() => _.forEach(paragraph.charts, (chart) => chart.api.update()), 100);
        }

        function _updateChartsWithData(paragraph, newDatum) {
            $timeout(() => {
                if (!paragraph.chartTimeLineEnabled()) {
                    const chartDatum = paragraph.charts[0].data;

                    chartDatum.length = 0;

                    _.forEach(newDatum, (series) => chartDatum.push(series));
                }

                paragraph.charts[0].api.update();
            });
        }

        function _yAxisLabel(paragraph) {
            const cols = paragraph.chartValCols;

            const tml = paragraph.chartTimeLineEnabled();

            return _.isEmpty(cols) ? 'Y' : _.map(cols, function(col) {
                let lbl = col.label;

                if (tml)
                    lbl += ' [' + col.aggFx + ']';

                return lbl;
            }).join(', ');
        }

        function _barChart(paragraph) {
            const datum = _chartDatum(paragraph);

            if (_.isEmpty(paragraph.charts)) {
                const stacked = paragraph.chartsOptions && paragraph.chartsOptions.barChart
                    ? paragraph.chartsOptions.barChart.stacked
                    : true;

                const options = {
                    chart: {
                        type: 'multiBarChart',
                        height: 400,
                        margin: {left: 70},
                        duration: 0,
                        x: _xX,
                        y: _yY,
                        xAxis: {
                            axisLabel: _xAxisLabel(paragraph),
                            tickFormat: paragraph.chartTimeLineEnabled() ? _xAxisTimeFormat : _xAxisWithLabelFormat(paragraph),
                            showMaxMin: false
                        },
                        yAxis: {
                            axisLabel: _yAxisLabel(paragraph),
                            tickFormat: _yAxisFormat
                        },
                        color: IgniteChartColors,
                        stacked,
                        showControls: true,
                        legend: {
                            vers: 'furious',
                            margin: {right: -15}
                        }
                    }
                };

                paragraph.charts = [{options, data: datum}];

                _updateCharts(paragraph);
            }
            else
                _updateChartsWithData(paragraph, datum);
        }

        function _pieChartDatum(paragraph) {
            const datum = [];

            if (paragraph.chartColumnsConfigured() && !paragraph.chartTimeLineEnabled()) {
                paragraph.chartValCols.forEach(function(valCol) {
                    let index = paragraph.total;

                    const values = _.map(paragraph.rows, (row) => {
                        const xCol = paragraph.chartKeyCols[0].value;

                        const v = {
                            x: xCol < 0 ? index : row[xCol],
                            y: _chartNumber(row, valCol.value, index)
                        };

                        // Workaround for known problem with zero values on Pie chart.
                        if (v.y === 0)
                            v.y = 0.0001;

                        index++;

                        return v;
                    });

                    datum.push({series: paragraph.chartKeyCols[0].label, key: valCol.label, values});
                });
            }

            return datum;
        }

        function _pieChart(paragraph) {
            let datum = _pieChartDatum(paragraph);

            if (datum.length === 0)
                datum = [{values: []}];

            paragraph.charts = _.map(datum, function(data) {
                return {
                    options: {
                        chart: {
                            type: 'pieChart',
                            height: 400,
                            duration: 0,
                            x: _xX,
                            y: _yY,
                            showLabels: true,
                            labelThreshold: 0.05,
                            labelType: 'percent',
                            donut: true,
                            donutRatio: 0.35,
                            legend: {
                                vers: 'furious',
                                margin: {right: -15}
                            }
                        },
                        title: {
                            enable: true,
                            text: data.key
                        }
                    },
                    data: data.values
                };
            });

            _updateCharts(paragraph);
        }

        function _lineChart(paragraph) {
            const datum = _chartDatum(paragraph);

            if (_.isEmpty(paragraph.charts)) {
                const options = {
                    chart: {
                        type: 'lineChart',
                        height: 400,
                        margin: { left: 70 },
                        duration: 0,
                        x: _xX,
                        y: _yY,
                        xAxis: {
                            axisLabel: _xAxisLabel(paragraph),
                            tickFormat: paragraph.chartTimeLineEnabled() ? _xAxisTimeFormat : _xAxisWithLabelFormat(paragraph),
                            showMaxMin: false
                        },
                        yAxis: {
                            axisLabel: _yAxisLabel(paragraph),
                            tickFormat: _yAxisFormat
                        },
                        color: IgniteChartColors,
                        useInteractiveGuideline: true,
                        legend: {
                            vers: 'furious',
                            margin: {right: -15}
                        }
                    }
                };

                paragraph.charts = [{options, data: datum}];

                _updateCharts(paragraph);
            }
            else
                _updateChartsWithData(paragraph, datum);
        }

        function _areaChart(paragraph) {
            const datum = _chartDatum(paragraph);

            if (_.isEmpty(paragraph.charts)) {
                const style = paragraph.chartsOptions && paragraph.chartsOptions.areaChart
                    ? paragraph.chartsOptions.areaChart.style
                    : 'stack';

                const options = {
                    chart: {
                        type: 'stackedAreaChart',
                        height: 400,
                        margin: {left: 70},
                        duration: 0,
                        x: _xX,
                        y: _yY,
                        xAxis: {
                            axisLabel: _xAxisLabel(paragraph),
                            tickFormat: paragraph.chartTimeLineEnabled() ? _xAxisTimeFormat : _xAxisWithLabelFormat(paragraph),
                            showMaxMin: false
                        },
                        yAxis: {
                            axisLabel: _yAxisLabel(paragraph),
                            tickFormat: _yAxisFormat
                        },
                        color: IgniteChartColors,
                        style,
                        legend: {
                            vers: 'furious',
                            margin: {right: -15}
                        }
                    }
                };

                paragraph.charts = [{options, data: datum}];

                _updateCharts(paragraph);
            }
            else
                _updateChartsWithData(paragraph, datum);
        }

        function _chartApplySettings(paragraph, resetCharts) {
            if (resetCharts)
                paragraph.charts = [];

            if (paragraph.chart() && paragraph.nonEmpty()) {
                switch (paragraph.result) {
                    case 'bar':
                        _barChart(paragraph);
                        break;

                    case 'pie':
                        _pieChart(paragraph);
                        break;

                    case 'line':
                        _lineChart(paragraph);
                        break;

                    case 'area':
                        _areaChart(paragraph);
                        break;

                    default:
                }
            }
        }

        $scope.chartRemoveKeyColumn = function(paragraph, index) {
            paragraph.chartKeyCols.splice(index, 1);

            _chartApplySettings(paragraph, true);
        };

        $scope.chartRemoveValColumn = function(paragraph, index) {
            paragraph.chartValCols.splice(index, 1);

            _chartApplySettings(paragraph, true);
        };

        $scope.chartAcceptKeyColumn = function(paragraph, item) {
            const accepted = _.findIndex(paragraph.chartKeyCols, item) < 0;

            if (accepted) {
                paragraph.chartKeyCols = [item];

                _chartApplySettings(paragraph, true);
            }

            return false;
        };

        const _numberClasses = ['java.math.BigDecimal', 'java.lang.Byte', 'java.lang.Double',
            'java.lang.Float', 'java.lang.Integer', 'java.lang.Long', 'java.lang.Short'];

        const _numberType = function(cls) {
            return _.includes(_numberClasses, cls);
        };

        $scope.chartAcceptValColumn = function(paragraph, item) {
            const valCols = paragraph.chartValCols;

            const accepted = _.findIndex(valCols, item) < 0 && item.value >= 0 && _numberType(item.type);

            if (accepted) {
                if (valCols.length === MAX_VAL_COLS - 1)
                    valCols.shift();

                valCols.push(item);

                _chartApplySettings(paragraph, true);
            }

            return false;
        };

        $scope.scrollParagraphs = [];

        $scope.rebuildScrollParagraphs = function() {
            $scope.scrollParagraphs = $scope.notebook.paragraphs.map(function(paragraph) {
                return {
                    text: paragraph.name,
                    click: 'scrollToParagraph("' + paragraph.id + '")'
                };
            });
        };

        $scope.scrollToParagraph = (id) => {
            const idx = _.findIndex($scope.notebook.paragraphs, {id});

            if (idx >= 0) {
                if (!_.includes($scope.notebook.expandedParagraphs, idx))
                    $scope.notebook.expandedParagraphs = $scope.notebook.expandedParagraphs.concat([idx]);

                if ($scope.notebook.paragraphs[idx].ace)
                    setTimeout(() => $scope.notebook.paragraphs[idx].ace.focus());
            }

            $location.hash(id);

            $anchorScroll();
        };

        const _hideColumn = (col) => col.fieldName !== '_KEY' && col.fieldName !== '_VAL';

        const _allColumn = () => true;

        $scope.aceInit = function(paragraph) {
            return function(editor) {
                editor.setAutoScrollEditorIntoView(true);
                editor.$blockScrolling = Infinity;

                const renderer = editor.renderer;

                renderer.setHighlightGutterLine(false);
                renderer.setShowPrintMargin(false);
                renderer.setOption('fontFamily', 'monospace');
                renderer.setOption('fontSize', '14px');
                renderer.setOption('minLines', '5');
                renderer.setOption('maxLines', '15');

                editor.setTheme('ace/theme/chrome');

                Object.defineProperty(paragraph, 'ace', { value: editor });
            };
        };

        /**
         * Update caches list.
         */
        const _refreshCaches = () => {
            return agentMgr.publicCacheNames()
                .then((cacheNames) => {
                    $scope.caches = _.sortBy(_.map(cacheNames, (name) => ({
                        label: maskCacheName(name, true),
                        value: name
                    })), (cache) => cache.label.toLowerCase());

                    _.forEach($scope.notebook.paragraphs, (paragraph) => {
                        if (!_.includes(cacheNames, paragraph.cacheName))
                            paragraph.cacheName = _.head(cacheNames);
                    });

                    // Await for demo caches.
                    if (!$ctrl.demoStarted && $root.IgniteDemoMode && nonEmpty(cacheNames)) {
                        $ctrl.demoStarted = true;

                        Loading.finish('sqlLoading');

                        _.forEach($scope.notebook.paragraphs, (paragraph) => $scope.execute(paragraph));
                    }

                    $scope.$applyAsync();
                })
                .catch((err) => Messages.showError(err));
        };

        const _startWatch = () => {
            const finishLoading$ = defer(() => {
                if (!$root.IgniteDemoMode)
                    Loading.finish('sqlLoading');
            }).pipe(take(1));

            const refreshCaches = (period) => {
                return merge(timer(0, period).pipe(exhaustMap(() => _refreshCaches())), finishLoading$);
            };

            const cluster$ = agentMgr.connectionSbj.pipe(
                pluck('cluster'),
                distinctUntilChanged(),
                tap((cluster) => {
                    this.clusterIsAvailable = (!!cluster && cluster.active === true) || agentMgr.isDemoMode();
                })
            );

            this.refresh$ = cluster$.pipe(
                switchMap((cluster) => {
                    if (!cluster && !agentMgr.isDemoMode()) {
                        return of(EMPTY).pipe(
                            tap(() => {
                                $scope.caches = [];
                            })
                        );
                    }

                    return of(cluster).pipe(
                        tap(() => Loading.start('sqlLoading')),
                        tap(() => {
                            _.forEach($scope.notebook.paragraphs, (paragraph) => {
                                paragraph.reset($interval);
                            });
                        }),
                        switchMap(() => refreshCaches(5000))
                    );
                })
            );

            this.subscribers$ = merge(this.refresh$).subscribe();
        };

        const _newParagraph = (paragraph) => {
            return new Paragraph($animate, $timeout, JavaTypes, errorParser, paragraph);
        };

        Notebook.find($state.params.noteId)
            .then((notebook) => {
                $scope.notebook = _.cloneDeep(notebook);

                $scope.notebook_name = $scope.notebook.name;

                if (!$scope.notebook.expandedParagraphs)
                    $scope.notebook.expandedParagraphs = [];

                if (!$scope.notebook.paragraphs)
                    $scope.notebook.paragraphs = [];

                $scope.notebook.paragraphs = _.map($scope.notebook.paragraphs, (p) => _newParagraph(p));

                if (_.isEmpty($scope.notebook.paragraphs))
                    $scope.addQuery();
                else
                    $scope.rebuildScrollParagraphs();
            })
            .then(() => {
                if ($root.IgniteDemoMode && sessionStorage.showDemoInfo !== 'true') {
                    sessionStorage.showDemoInfo = 'true';

                    this.DemoInfo.show().then(_startWatch);
                } else
                    _startWatch();
            })
            .catch(() => {
                $scope.notebookLoadFailed = true;

                Loading.finish('sqlLoading');
            });

        $scope.renameNotebook = (name) => {
            if (!name)
                return;

            if ($scope.notebook.name !== name) {
                const prevName = $scope.notebook.name;

                $scope.notebook.name = name;

                Notebook.save($scope.notebook)
                    .then(() => $scope.notebook.edit = false)
                    .catch((err) => {
                        $scope.notebook.name = prevName;

                        Messages.showError(err);
                    });
            }
            else
                $scope.notebook.edit = false;
        };

        $scope.removeNotebook = (notebook) => Notebook.remove(notebook);

        $scope.addParagraph = (paragraph, sz) => {
            if ($scope.caches && $scope.caches.length > 0)
                paragraph.cacheName = _.head($scope.caches).value;

            $scope.notebook.paragraphs.push(paragraph);

            $scope.notebook.expandedParagraphs.push(sz);

            $scope.rebuildScrollParagraphs();

            $location.hash(paragraph.id);
        };

        $scope.addQuery = function() {
            const sz = $scope.notebook.paragraphs.length;

            ActivitiesData.post({ group: 'sql', action: '/queries/add/query' });

            const paragraph = _newParagraph({
                name: 'Query' + (sz === 0 ? '' : sz),
                query: '',
                pageSize: $scope.pageSizesOptions[1].value,
                timeLineSpan: $scope.timeLineSpans[0],
                result: 'none',
                rate: {
                    value: 1,
                    unit: 60000,
                    installed: false
                },
                qryType: 'query',
                lazy: true
            });

            $scope.addParagraph(paragraph, sz);

            $timeout(() => {
                $anchorScroll();

                paragraph.ace.focus();
            });
        };

        $scope.addScan = function() {
            const sz = $scope.notebook.paragraphs.length;

            ActivitiesData.post({ group: 'sql', action: '/queries/add/scan' });

            const paragraph = _newParagraph({
                name: 'Scan' + (sz === 0 ? '' : sz),
                query: '',
                pageSize: $scope.pageSizesOptions[1].value,
                timeLineSpan: $scope.timeLineSpans[0],
                result: 'none',
                rate: {
                    value: 1,
                    unit: 60000,
                    installed: false
                },
                qryType: 'scan'
            });

            $scope.addParagraph(paragraph, sz);
        };

        function _saveChartSettings(paragraph) {
            if (!_.isEmpty(paragraph.charts)) {
                const chart = paragraph.charts[0].api.getScope().chart;

                if (!LegacyUtils.isDefined(paragraph.chartsOptions))
                    paragraph.chartsOptions = {barChart: {stacked: true}, areaChart: {style: 'stack'}};

                switch (paragraph.result) {
                    case 'bar':
                        paragraph.chartsOptions.barChart.stacked = chart.stacked();

                        break;

                    case 'area':
                        paragraph.chartsOptions.areaChart.style = chart.style();

                        break;

                    default:
                }
            }
        }

        $scope.setResult = function(paragraph, new_result) {
            if (paragraph.result === new_result)
                return;

            _saveChartSettings(paragraph);

            paragraph.result = new_result;

            if (paragraph.chart())
                _chartApplySettings(paragraph, true);
        };

        $scope.resultEq = function(paragraph, result) {
            return (paragraph.result === result);
        };

        $scope.paragraphExpanded = function(paragraph) {
            const paragraph_idx = _.findIndex($scope.notebook.paragraphs, function(item) {
                return paragraph === item;
            });

            const panel_idx = _.findIndex($scope.notebook.expandedParagraphs, function(item) {
                return paragraph_idx === item;
            });

            return panel_idx >= 0;
        };

        const _columnFilter = function(paragraph) {
            return paragraph.disabledSystemColumns || paragraph.systemColumns ? _allColumn : _hideColumn;
        };

        const _notObjectType = function(cls) {
            return LegacyUtils.isJavaBuiltInClass(cls);
        };

        function _retainColumns(allCols, curCols, acceptableType, xAxis, unwantedCols) {
            const retainedCols = [];

            const availableCols = xAxis ? allCols : _.filter(allCols, function(col) {
                return col.value >= 0;
            });

            if (availableCols.length > 0) {
                curCols.forEach(function(curCol) {
                    const col = _.find(availableCols, {label: curCol.label});

                    if (col && acceptableType(col.type)) {
                        col.aggFx = curCol.aggFx;

                        retainedCols.push(col);
                    }
                });

                // If nothing was restored, add first acceptable column.
                if (_.isEmpty(retainedCols)) {
                    let col;

                    if (unwantedCols)
                        col = _.find(availableCols, (avCol) => !_.find(unwantedCols, {label: avCol.label}) && acceptableType(avCol.type));

                    if (!col)
                        col = _.find(availableCols, (avCol) => acceptableType(avCol.type));

                    if (col)
                        retainedCols.push(col);
                }
            }

            return retainedCols;
        }

        const _rebuildColumns = function(paragraph) {
            _.forEach(_.groupBy(paragraph.meta, 'fieldName'), function(colsByName, fieldName) {
                const colsByTypes = _.groupBy(colsByName, 'typeName');

                const needType = _.keys(colsByTypes).length > 1;

                _.forEach(colsByTypes, function(colsByType, typeName) {
                    _.forEach(colsByType, function(col, ix) {
                        col.fieldName = (needType && !LegacyUtils.isEmptyString(typeName) ? typeName + '.' : '') + fieldName + (ix > 0 ? ix : '');
                    });
                });
            });

            paragraph.gridOptions.rebuildColumns();

            paragraph.chartColumns = _.reduce(paragraph.meta, (acc, col, idx) => {
                if (_notObjectType(col.fieldTypeName)) {
                    acc.push({
                        label: col.fieldName,
                        type: col.fieldTypeName,
                        aggFx: $scope.aggregateFxs[0],
                        value: idx.toString()
                    });
                }

                return acc;
            }, []);

            if (paragraph.chartColumns.length > 0) {
                paragraph.chartColumns.push(TIME_LINE);
                paragraph.chartColumns.push(ROW_IDX);
            }

            // We could accept onl not object columns for X axis.
            paragraph.chartKeyCols = _retainColumns(paragraph.chartColumns, paragraph.chartKeyCols, _notObjectType, true);

            // We could accept only numeric columns for Y axis.
            paragraph.chartValCols = _retainColumns(paragraph.chartColumns, paragraph.chartValCols, _numberType, false, paragraph.chartKeyCols);
        };

        $scope.toggleSystemColumns = function(paragraph) {
            if (paragraph.disabledSystemColumns)
                return;

            paragraph.columnFilter = _columnFilter(paragraph);

            paragraph.chartColumns = [];

            _rebuildColumns(paragraph);
        };

        const _showLoading = (paragraph, enable) => {
            if (paragraph.qryType === 'scan')
                paragraph.scanningInProgress = enable;

            paragraph.loading = enable;
        };

        const _fetchQueryResult = (paragraph, clearChart, res, qryArg) => {
            if (!_.isNil(res.rows)) {
                _processQueryResult(paragraph, clearChart, res);
                _tryStartRefresh(paragraph);

                $scope.$applyAsync();

                return;
            }

            const subscription = timer(100, 500).pipe(
                exhaustMap(() => agentMgr.queryFetchFistsPage(qryArg.nid, res.queryId, qryArg.pageSize)),
                filter((res) => !_.isNil(res.rows)),
                take(1),
                map((res) => _fetchQueryResult(paragraph, false, res, qryArg)),
                catchError((err) => {
                    if (paragraph.subscription) {
                        paragraph.subscription.unsubscribe();
                        paragraph.setError(err);

                        _showLoading(paragraph, false);
                        delete paragraph.subscription;

                        $scope.$applyAsync();
                    }

                    return of(err);
                })
            ).subscribe();

            Object.defineProperty(paragraph, 'subscription', {value: subscription, configurable: true});

            return subscription;
        };

        /**
         * @param {Object} paragraph Query
         * @param {Boolean} clearChart Flag is need clear chart model.
         * @param {{columns: Array, rows: Array, responseNodeId: String, queryId: int, hasMore: Boolean}} res Query results.
         * @private
         */
        const _processQueryResult = (paragraph, clearChart, res) => {
            const prevKeyCols = paragraph.chartKeyCols;
            const prevValCols = paragraph.chartValCols;

            if (paragraph.subscription) {
                paragraph.subscription.unsubscribe();
                delete paragraph.subscription;
            }

            if (!_.eq(paragraph.meta, res.columns)) {
                paragraph.meta = [];

                paragraph.chartColumns = [];

                if (!LegacyUtils.isDefined(paragraph.chartKeyCols))
                    paragraph.chartKeyCols = [];

                if (!LegacyUtils.isDefined(paragraph.chartValCols))
                    paragraph.chartValCols = [];

                if (res.columns.length) {
                    const _key = _.find(res.columns, {fieldName: '_KEY'});
                    const _val = _.find(res.columns, {fieldName: '_VAL'});

                    paragraph.disabledSystemColumns = !(_key && _val) ||
                        (res.columns.length === 2 && _key && _val) ||
                        (res.columns.length === 1 && (_key || _val));
                }

                paragraph.columnFilter = _columnFilter(paragraph);

                paragraph.meta = res.columns;

                _rebuildColumns(paragraph);
            }

            paragraph.page = 1;

            paragraph.total = 0;

            paragraph.duration = res.duration;

            paragraph.queryId = res.hasMore ? res.queryId : null;

            paragraph.resNodeId = res.responseNodeId;

            paragraph.setError({message: ''});

            // Prepare explain results for display in table.
            if (paragraph.queryArgs.query && paragraph.queryArgs.query.startsWith('EXPLAIN') && res.rows) {
                paragraph.rows = [];

                res.rows.forEach((row, i) => {
                    const line = res.rows.length - 1 === i ? row[0] : row[0] + '\n';

                    line.replace(/\"/g, '').split('\n').forEach((ln) => paragraph.rows.push([ln]));
                });
            }
            else
                paragraph.rows = res.rows;

            paragraph.gridOptions.adjustHeight(paragraph.rows.length);

            const chartHistory = paragraph.chartHistory;

            // Clear history on query change.
            if (clearChart) {
                chartHistory.length = 0;

                _.forEach(paragraph.charts, (chart) => chart.data.length = 0);
            }

            // Add results to history.
            chartHistory.push({tm: new Date(), rows: paragraph.rows});

            // Keep history size no more than max length.
            while (chartHistory.length > HISTORY_LENGTH)
                chartHistory.shift();

            _showLoading(paragraph, false);

            if (_.isNil(paragraph.result) || paragraph.result === 'none' || paragraph.scanExplain())
                paragraph.result = 'table';
            else if (paragraph.chart()) {
                let resetCharts = clearChart;

                if (!resetCharts) {
                    const curKeyCols = paragraph.chartKeyCols;
                    const curValCols = paragraph.chartValCols;

                    resetCharts = !prevKeyCols || !prevValCols ||
                        prevKeyCols.length !== curKeyCols.length ||
                        prevValCols.length !== curValCols.length;
                }

                _chartApplySettings(paragraph, resetCharts);
            }
        };

        const _closeOldQuery = (paragraph) => {
            const nid = paragraph.resNodeId;

            if (paragraph.queryId) {
                const qryId = paragraph.queryId;
                delete paragraph.queryId;

                return agentMgr.queryClose(nid, qryId);
            }

            return $q.when();
        };

        $scope.cancelQuery = (paragraph) => {
            if (paragraph.subscription) {
                paragraph.subscription.unsubscribe();
                delete paragraph.subscription;
            }

            _showLoading(paragraph, false);
            this.$scope.stopRefresh(paragraph);

            _closeOldQuery(paragraph)
                .then(() => _showLoading(paragraph, false))
                .catch((err) => {
                    _showLoading(paragraph, false);
                    paragraph.setError(err);
                });
        };

        $scope.cancelQueryAvailable = (paragraph) => {
            return !!paragraph.subscription;
        };

        /**
         * @param {String} name Cache name.
         * @param {Array.<String>} nids Cache name.
         * @return {Promise<Array.<{nid: string, ip: string, version:string, gridName: string, os: string, client: boolean}>>}
         */
        const cacheNodesModel = (name, nids) => {
            return agentMgr.topology(true)
                .then((nodes) =>
                    _.reduce(nodes, (acc, node) => {
                        if (_.includes(nids, node.nodeId)) {
                            acc.push({
                                nid: node.nodeId.toUpperCase(),
                                ip: _.head(node.attributes['org.apache.ignite.ips'].split(', ')),
                                version: node.attributes['org.apache.ignite.build.ver'],
                                gridName: node.attributes['org.apache.ignite.ignite.name'],
                                os: `${node.attributes['os.name']} ${node.attributes['os.arch']} ${node.attributes['os.version']}`,
                                client: node.attributes['org.apache.ignite.cache.client']
                            });
                        }

                        return acc;
                    }, [])
                );
        };

        /**
         * @param {string} name Cache name.
         * @param {boolean} local Local query.
         * @return {Promise<string>} Nid
         */
        const _chooseNode = (name, local) => {
            if (_.isEmpty(name))
                return Promise.resolve(null);

            return agentMgr.cacheNodes(name)
                .then((nids) => {
                    if (local) {
                        return cacheNodesModel(name, nids)
                            .then((nodes) => Nodes.selectNode(nodes, name).catch(() => {}))
                            .then((selectedNids) => _.head(selectedNids));
                    }

                    return nids[_.random(0, nids.length - 1)];
                })
                .catch(Messages.showError);
        };

        const _executeRefresh = (paragraph) => {
            const args = paragraph.queryArgs;

            agentMgr.awaitCluster()
                .then(() => _closeOldQuery(paragraph))
                .then(() => args.localNid || _chooseNode(args.cacheName, false))
                .then((nid) => {
                    const qryArg = {
                        nid,
                        cacheName: args.cacheName,
                        query: args.query,
                        nonCollocatedJoins: args.nonCollocatedJoins,
                        enforceJoinOrder: args.enforceJoinOrder,
                        replicatedOnly: false,
                        local: !!args.localNid,
                        pageSize: args.pageSize,
                        lazy: args.lazy,
                        collocated: args.collocated
                    };

                    return agentMgr.querySql(qryArg)
                        .then((res) => _fetchQueryResult(paragraph, false, res, qryArg));
                })
                .catch((err) => paragraph.setError(err));
        };

        const _tryStartRefresh = function(paragraph) {
            _tryStopRefresh(paragraph);

            if (_.get(paragraph, 'rate.installed') && paragraph.queryExecuted()) {
                $scope.chartAcceptKeyColumn(paragraph, TIME_LINE);

                const delay = paragraph.rate.value * paragraph.rate.unit;

                paragraph.rate.stopTime = $interval(_executeRefresh, delay, 0, false, paragraph);
            }
        };

        const addLimit = (query, limitSize) =>
            `SELECT * FROM (
            ${query} 
            ) LIMIT ${limitSize}`;

        $scope.nonCollocatedJoinsAvailable = () => {
            return Version.since(this.agentMgr.clusterVersion, NON_COLLOCATED_JOINS_SINCE);
        };

        $scope.collocatedJoinsAvailable = () => {
            return Version.since(this.agentMgr.clusterVersion, ...COLLOCATED_QUERY_SINCE);
        };

        $scope.enforceJoinOrderAvailable = () => {
            return Version.since(this.agentMgr.clusterVersion, ...ENFORCE_JOIN_SINCE);
        };

        $scope.lazyQueryAvailable = () => {
            return Version.since(this.agentMgr.clusterVersion, ...LAZY_QUERY_SINCE);
        };

        $scope.ddlAvailable = () => {
            return Version.since(this.agentMgr.clusterVersion, ...DDL_SINCE);
        };

        $scope.cacheNameForSql = (paragraph) => {
            return $scope.ddlAvailable() && !paragraph.useAsDefaultSchema ? null : paragraph.cacheName;
        };

        const _initQueryResult = (paragraph, res) => {
            paragraph.resNodeId = res.responseNodeId;
            paragraph.queryId = res.queryId;

            paragraph.rows = [];
            paragraph.gridOptions.adjustHeight(paragraph.rows.length);

            paragraph.meta = [];
            paragraph.setError({message: ''});

            paragraph.hasNext = false;
        };

        $scope.execute = (paragraph, local = false) => {
            const nonCollocatedJoins = !!paragraph.nonCollocatedJoins;
            const enforceJoinOrder = !!paragraph.enforceJoinOrder;
            const lazy = !!paragraph.lazy;
            const collocated = !!paragraph.collocated;

            $scope.queryAvailable(paragraph) && _chooseNode(paragraph.cacheName, local)
                .then((nid) => {
                    // If we are executing only selected part of query then Notebook shouldn't be saved.
                    if (!paragraph.partialQuery)
                        Notebook.save($scope.notebook).catch(Messages.showError);

                    paragraph.localQueryMode = local;
                    paragraph.prevQuery = paragraph.queryArgs ? paragraph.queryArgs.query : paragraph.query;

                    _showLoading(paragraph, true);

                    return _closeOldQuery(paragraph)
                        .then(() => {
                            const query = paragraph.partialQuery || paragraph.query;

                            const args = paragraph.queryArgs = {
                                type: 'QUERY',
                                cacheName: $scope.cacheNameForSql(paragraph),
                                query,
                                pageSize: paragraph.pageSize,
                                maxPages: paragraph.maxPages,
                                nonCollocatedJoins,
                                enforceJoinOrder,
                                localNid: local ? nid : null,
                                lazy,
                                collocated
                            };

                            ActivitiesData.post({ group: 'sql', action: '/queries/execute' });

                            const qry = args.maxPages ? addLimit(args.query, args.pageSize * args.maxPages) : query;
                            const qryArg = {
                                nid,
                                cacheName: args.cacheName,
                                query: qry,
                                nonCollocatedJoins,
                                enforceJoinOrder,
                                replicatedOnly: false,
                                local,
                                pageSize: args.pageSize,
                                lazy,
                                collocated
                            };

                            return agentMgr.querySql(qryArg)
                                .then((res) => {
                                    _initQueryResult(paragraph, res);

                                    return _fetchQueryResult(paragraph, true, res, qryArg);
                                });
                        })
                        .catch((err) => {
                            paragraph.setError(err);

                            _showLoading(paragraph, false);

                            $scope.stopRefresh(paragraph);

                            Messages.showError(err);
                        })
                        .then(() => paragraph.ace.focus());
                });
        };

        const _cancelRefresh = (paragraph) => {
            if (paragraph.rate && paragraph.rate.stopTime) {
                delete paragraph.queryArgs;

                paragraph.rate.installed = false;

                $interval.cancel(paragraph.rate.stopTime);

                delete paragraph.rate.stopTime;
            }
        };

        $scope.explain = (paragraph) => {
            const nonCollocatedJoins = !!paragraph.nonCollocatedJoins;
            const enforceJoinOrder = !!paragraph.enforceJoinOrder;
            const collocated = !!paragraph.collocated;

            if (!$scope.queryAvailable(paragraph))
                return;

            if (!paragraph.partialQuery)
                Notebook.save($scope.notebook).catch(Messages.showError);

            _cancelRefresh(paragraph);

            _showLoading(paragraph, true);

            _closeOldQuery(paragraph)
                .then(() => _chooseNode(paragraph.cacheName, false))
                .then((nid) => {
                    const args = paragraph.queryArgs = {
                        type: 'EXPLAIN',
                        cacheName: $scope.cacheNameForSql(paragraph),
                        query: 'EXPLAIN ' + (paragraph.partialQuery || paragraph.query),
                        pageSize: paragraph.pageSize
                    };

                    ActivitiesData.post({ group: 'sql', action: '/queries/explain' });

                    const qryArg = {
                        nid,
                        cacheName: args.cacheName,
                        query: args.query,
                        nonCollocatedJoins,
                        enforceJoinOrder,
                        replicatedOnly: false,
                        local: false,
                        pageSize: args.pageSize,
                        lazy: false, collocated
                    };

                    return agentMgr.querySql(qryArg)
                        .then((res) => {
                            _initQueryResult(paragraph, res);

                            return _fetchQueryResult(paragraph, true, res, qryArg);
                        });
                })
                .catch((err) => {
                    paragraph.setError(err);

                    _showLoading(paragraph, false);
                })
                .then(() => paragraph.ace.focus());
        };

        $scope.scan = (paragraph, local = false) => {
            const cacheName = paragraph.cacheName;
            const caseSensitive = !!paragraph.caseSensitive;
            const filter = paragraph.filter;
            const pageSize = paragraph.pageSize;

            $scope.scanAvailable(paragraph) && _chooseNode(cacheName, local)
                .then((nid) => {
                    paragraph.localQueryMode = local;

                    Notebook.save($scope.notebook)
                        .catch(Messages.showError);

                    _cancelRefresh(paragraph);

                    _showLoading(paragraph, true);

                    _closeOldQuery(paragraph)
                        .then(() => {
                            paragraph.queryArgs = {
                                type: 'SCAN',
                                cacheName,
                                filter,
                                regEx: false,
                                caseSensitive,
                                near: false,
                                pageSize,
                                localNid: local ? nid : null
                            };

                            ActivitiesData.post({ group: 'sql', action: '/queries/scan' });

                            const qryArg = {
                                nid,
                                cacheName,
                                filter,
                                regEx: false,
                                caseSensitive,
                                near: false,
                                local,
                                pageSize
                            };

                            return agentMgr.queryScan(qryArg).then((res) => {
                                _initQueryResult(paragraph, res);

                                return _fetchQueryResult(paragraph, true, res, qryArg);
                            });
                        })
                        .catch((err) => {
                            paragraph.setError(err);

                            _showLoading(paragraph, false);
                        });
                });
        };

        function _updatePieChartsWithData(paragraph, newDatum) {
            $timeout(() => {
                _.forEach(paragraph.charts, function(chart) {
                    const chartDatum = chart.data;

                    chartDatum.length = 0;

                    _.forEach(newDatum, function(series) {
                        if (chart.options.title.text === series.key)
                            _.forEach(series.values, (v) => chartDatum.push(v));
                    });
                });

                _.forEach(paragraph.charts, (chart) => chart.api.update());
            });
        }

        $scope.nextPage = (paragraph) => {
            _showLoading(paragraph, true);

            paragraph.queryArgs.pageSize = paragraph.pageSize;

            agentMgr.queryNextPage(paragraph.resNodeId, paragraph.queryId, paragraph.pageSize)
                .then((res) => {
                    paragraph.page++;

                    paragraph.total += paragraph.rows.length;

                    paragraph.duration = res.duration;

                    paragraph.rows = res.rows;

                    if (paragraph.chart()) {
                        if (paragraph.result === 'pie')
                            _updatePieChartsWithData(paragraph, _pieChartDatum(paragraph));
                        else
                            _updateChartsWithData(paragraph, _chartDatum(paragraph));
                    }

                    paragraph.gridOptions.adjustHeight(paragraph.rows.length);

                    _showLoading(paragraph, false);

                    if (!res.hasMore)
                        delete paragraph.queryId;
                })
                .catch((err) => {
                    paragraph.setError(err);

                    _showLoading(paragraph, false);
                })
                .then(() => paragraph.ace && paragraph.ace.focus());
        };

        const _export = (fileName, columnDefs, meta, rows, toClipBoard = false) => {
            const csvSeparator = this.CSV.getSeparator();
            let csvContent = '';

            const cols = [];
            const excludedCols = [];

            _.forEach(meta, (col, idx) => {
                if (columnDefs[idx].visible)
                    cols.push(_fullColName(col));
                else
                    excludedCols.push(idx);
            });

            csvContent += cols.join(csvSeparator) + '\n';

            _.forEach(rows, (row) => {
                cols.length = 0;

                if (Array.isArray(row)) {
                    _.forEach(row, (elem, idx) => {
                        if (_.includes(excludedCols, idx))
                            return;

                        cols.push(_.isUndefined(elem) ? '' : JSON.stringify(elem));
                    });
                }
                else {
                    _.forEach(columnDefs, (col) => {
                        if (col.visible) {
                            const elem = row[col.fieldName];

                            cols.push(_.isUndefined(elem) ? '' : JSON.stringify(elem));
                        }
                    });
                }

                csvContent += cols.join(csvSeparator) + '\n';
            });

            if (toClipBoard)
                IgniteCopyToClipboard.copy(csvContent);
            else
                LegacyUtils.download('text/csv', fileName, csvContent);
        };

        /**
         * Generate file name with query results.
         *
         * @param paragraph {Object} Query paragraph .
         * @param all {Boolean} All result export flag.
         * @returns {string}
         */
        const exportFileName = (paragraph, all) => {
            const args = paragraph.queryArgs;

            if (args.type === 'SCAN')
                return `export-scan-${args.cacheName}-${paragraph.name}${all ? '-all' : ''}.csv`;

            return `export-query-${paragraph.name}${all ? '-all' : ''}.csv`;
        };

        $scope.exportCsvToClipBoard = (paragraph) => {
            _export(exportFileName(paragraph, false), paragraph.gridOptions.columnDefs, paragraph.meta, paragraph.rows, true);
        };

        $scope.exportCsv = function(paragraph) {
            _export(exportFileName(paragraph, false), paragraph.gridOptions.columnDefs, paragraph.meta, paragraph.rows);

            // paragraph.gridOptions.api.exporter.csvExport(uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE);
        };

        $scope.exportPdf = function(paragraph) {
            paragraph.gridOptions.api.exporter.pdfExport(uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE);
        };

        $scope.exportCsvAll = (paragraph) => {
            paragraph.csvIsPreparing = true;

            const args = paragraph.queryArgs;

            return Promise.resolve(args.localNid || _chooseNode(args.cacheName, false))
                .then((nid) => args.type === 'SCAN'
                    ? agentMgr.queryScanGetAll({
                        nid,
                        cacheName: args.cacheName,
                        filter: args.query,
                        regEx: !!args.regEx,
                        caseSensitive: !!args.caseSensitive,
                        near: !!args.near,
                        local: !!args.localNid
                    })
                    : agentMgr.querySqlGetAll({
                        nid,
                        cacheName: args.cacheName,
                        query: args.query,
                        nonCollocatedJoins: !!args.nonCollocatedJoins,
                        enforceJoinOrder: !!args.enforceJoinOrder,
                        replicatedOnly: false,
                        local: !!args.localNid,
                        lazy: !!args.lazy,
                        collocated: !!args.collocated
                    }))
                .then((res) => _export(exportFileName(paragraph, true), paragraph.gridOptions.columnDefs, res.columns, res.rows))
                .catch(Messages.showError)
                .then(() => {
                    paragraph.csvIsPreparing = false;

                    return paragraph.ace && paragraph.ace.focus();
                });
        };

        // $scope.exportPdfAll = function(paragraph) {
        //    $http.post('/api/v1/agent/query/getAll', {query: paragraph.query, cacheName: paragraph.cacheName})
        //    .then(({data}) {
        //        _export(paragraph.name + '-all.csv', data.meta, data.rows);
        //    })
        //    .catch(Messages.showError);
        // };

        $scope.rateAsString = function(paragraph) {
            if (paragraph.rate && paragraph.rate.installed) {
                const idx = _.findIndex($scope.timeUnit, function(unit) {
                    return unit.value === paragraph.rate.unit;
                });

                if (idx >= 0)
                    return ' ' + paragraph.rate.value + $scope.timeUnit[idx].short;

                paragraph.rate.installed = false;
            }

            return '';
        };

        $scope.startRefresh = function(paragraph, value, unit) {
            paragraph.rate.value = value;
            paragraph.rate.unit = unit;
            paragraph.rate.installed = true;

            if (paragraph.queryExecuted() && !paragraph.scanExplain())
                _executeRefresh(paragraph);
        };

        $scope.stopRefresh = function(paragraph) {
            paragraph.rate.installed = false;

            _tryStopRefresh(paragraph);
        };

        $scope.paragraphTimeSpanVisible = function(paragraph) {
            return paragraph.timeLineSupported() && paragraph.chartTimeLineEnabled();
        };

        $scope.paragraphTimeLineSpan = function(paragraph) {
            if (paragraph && paragraph.timeLineSpan)
                return paragraph.timeLineSpan.toString();

            return '1';
        };

        $scope.applyChartSettings = function(paragraph) {
            _chartApplySettings(paragraph, true);
        };

        $scope.queryAvailable = function(paragraph) {
            return paragraph.query && !paragraph.loading;
        };

        $scope.queryTooltip = function(paragraph, action) {
            if ($scope.queryAvailable(paragraph))
                return;

            if (paragraph.loading)
                return 'Waiting for server response';

            return 'Input text to ' + action;
        };

        $scope.scanAvailable = function(paragraph) {
            return $scope.caches.length && !(paragraph.loading || paragraph.csvIsPreparing);
        };

        $scope.scanTooltip = function(paragraph) {
            if ($scope.scanAvailable(paragraph))
                return;

            if (paragraph.loading)
                return 'Waiting for server response';

            return 'Select cache to export scan results';
        };

        $scope.clickableMetadata = function(node) {
            return node.type.slice(0, 5) !== 'index';
        };

        $scope.dblclickMetadata = function(paragraph, node) {
            paragraph.ace.insert(node.name);

            setTimeout(() => paragraph.ace.focus(), 100);
        };

        $scope.importMetadata = function() {
            Loading.start('loadingCacheMetadata');

            $scope.metadata = [];

            agentMgr.metadata()
                .then((metadata) => {
                    $scope.metadata = _.sortBy(_.filter(metadata, (meta) => {
                        const cache = _.find($scope.caches, { value: meta.cacheName });

                        if (cache) {
                            meta.name = (cache.sqlSchema || '"' + meta.cacheName + '"') + '.' + meta.typeName;
                            meta.displayName = (cache.sqlSchema || meta.maskedName) + '.' + meta.typeName;

                            if (cache.sqlSchema)
                                meta.children.unshift({type: 'plain', name: 'cacheName: ' + meta.maskedName, maskedName: meta.maskedName});

                            meta.children.unshift({type: 'plain', name: 'mode: ' + cache.mode, maskedName: meta.maskedName});
                        }

                        return cache;
                    }), 'name');
                })
                .catch(Messages.showError)
                .then(() => Loading.finish('loadingCacheMetadata'));
        };

        $scope.showResultQuery = function(paragraph) {
            if (!_.isNil(paragraph)) {
                const scope = $scope.$new();

                if (paragraph.queryArgs.type === 'SCAN') {
                    scope.title = 'SCAN query';

                    const filter = paragraph.queryArgs.filter;

                    if (_.isEmpty(filter))
                        scope.content = [`SCAN query for cache: <b>${maskCacheName(paragraph.queryArgs.cacheName, true)}</b>`];
                    else
                        scope.content = [`SCAN query for cache: <b>${maskCacheName(paragraph.queryArgs.cacheName, true)}</b> with filter: <b>${filter}</b>`];
                }
                else if (paragraph.queryArgs.query .startsWith('EXPLAIN ')) {
                    scope.title = 'Explain query';
                    scope.content = paragraph.queryArgs.query.split(/\r?\n/);
                }
                else {
                    scope.title = 'SQL query';
                    scope.content = paragraph.queryArgs.query.split(/\r?\n/);
                }

                // Attach duration and selected node info
                scope.meta = `Duration: ${$filter('duration')(paragraph.duration)}.`;
                scope.meta += paragraph.localQueryMode ? ` Node ID8: ${id8(paragraph.resNodeId)}` : '';

                // Show a basic modal from a controller
                $modal({scope, templateUrl: messageTemplateUrl, show: true});
            }
        };

        $scope.showStackTrace = function(paragraph) {
            if (!_.isNil(paragraph)) {
                const scope = $scope.$new();

                scope.title = 'Error details';
                scope.content = [];

                const tab = '&nbsp;&nbsp;&nbsp;&nbsp;';

                const addToTrace = (item) => {
                    if (nonNil(item)) {
                        scope.content.push((scope.content.length > 0 ? tab : '') + errorParser.extractFullMessage(item));

                        addToTrace(item.cause);

                        _.forEach(item.suppressed, (sup) => addToTrace(sup));
                    }
                };

                addToTrace(paragraph.error.root);

                // Show a basic modal from a controller
                $modal({scope, templateUrl: messageTemplateUrl, show: true});
            }
        };

        $window.addEventListener('beforeunload', () => {
            this._closeOpenedQueries(this.$scope.notebook.paragraphs);
        });
    }

    _closeOpenedQueries(paragraphs) {
        _.forEach(paragraphs, ({queryId, subscription, resNodeId}) => {
            if (subscription)
                subscription.unsubscribe();

            if (queryId) {
                this.agentMgr.queryClose(resNodeId, queryId)
                    .catch(() => { /* No-op. */ });
            }
        });
    }

    scanActions: QueryActions<Paragraph & {type: 'scan'}> = [
        {
            text: 'Scan',
            click: (p) => this.$scope.scan(p),
            available: (p) => this.$scope.scanAvailable(p)
        },
        {
            text: 'Scan on selected node',
            click: (p) => this.$scope.scan(p, true),
            available: (p) => this.$scope.scanAvailable(p)
        },
        {text: 'Rename', click: (p) => this.renameParagraph(p), available: () => true},
        {text: 'Remove', click: (p) => this.removeParagraph(p), available: () => true}
    ];

    queryActions: QueryActions<Paragraph & {type: 'query'}> = [
        {
            text: 'Execute',
            click: (p) => this.$scope.execute(p),
            available: (p) => this.$scope.queryAvailable(p)
        },
        {
            text: 'Execute on selected node',
            click: (p) => this.$scope.execute(p, true),
            available: (p) => this.$scope.queryAvailable(p)
        },
        {
            text: 'Explain',
            click: (p) => this.$scope.explain(p),
            available: (p) => this.$scope.queryAvailable(p)
        },
        {text: 'Rename', click: (p) => this.renameParagraph(p), available: () => true},
        {text: 'Remove', click: (p) => this.removeParagraph(p), available: () => true}
    ];

    async renameParagraph(paragraph: Paragraph) {
        try {
            const newName = await this.IgniteInput.input('Rename Query', 'New query name:', paragraph.name);

            if (paragraph.name !== newName) {
                paragraph.name = newName;

                this.$scope.rebuildScrollParagraphs();

                await this.Notebook.save(this.$scope.notebook)
                    .catch(this.Messages.showError);
            }
        }
        catch (ignored) {
            // No-op.
        }
    }

    async removeParagraph(paragraph: Paragraph) {
        try {
            await this.Confirm.confirm('Are you sure you want to remove query: "' + paragraph.name + '"?');
            this.$scope.stopRefresh(paragraph);

            this._closeOpenedQueries([paragraph]);

            const paragraph_idx = _.findIndex(this.$scope.notebook.paragraphs, (item) => paragraph === item);
            const panel_idx = _.findIndex(this.$scope.expandedParagraphs, (item) => paragraph_idx === item);

            if (panel_idx >= 0)
                this.$scope.expandedParagraphs.splice(panel_idx, 1);

            this.$scope.notebook.paragraphs.splice(paragraph_idx, 1);
            this.$scope.rebuildScrollParagraphs();

            await this.Notebook.save(this.$scope.notebook)
                .catch(this.Messages.showError);
        }
        catch (ignored) {
            // No-op.
        }
    }

    isParagraphOpened(index: number) {
        return this.$scope.notebook.expandedParagraphs.includes(index);
    }

    onParagraphClose(index: number) {
        const expanded = this.$scope.notebook.expandedParagraphs;
        expanded.splice(expanded.indexOf(index), 1);
    }

    onParagraphOpen(index: number) {
        this.$scope.notebook.expandedParagraphs.push(index);
    }

    $onDestroy() {
        this._closeOpenedQueries(this.$scope.notebook.paragraphs);

        if (this.subscribers$)
            this.subscribers$.unsubscribe();
    }
}
