text:
"use strict";
var $ = require("jquery"),
    when = require("../../integration/jquery/deferred").when,
    Class = require("../../core/class"),
    stringUtils = require("../../core/utils/string"),
    commonUtils = require("../../core/utils/common"),
    virtualScrolling = require("../grid_core/ui.grid_core.virtual_scrolling"),
    stateStoring = require("../grid_core/ui.grid_core.state_storing"),
    PivotGridDataSource = require("./data_source"),
    pivotGridUtils = require("./ui.pivot_grid.utils"),
    foreachTree = pivotGridUtils.foreachTree,
    foreachTreeAsync = pivotGridUtils.foreachTreeAsync,
    createPath = pivotGridUtils.createPath,
    formatValue = pivotGridUtils.formatValue,
    math = Math,
    GRAND_TOTAL_TYPE = "GT",
    TOTAL_TYPE = "T",
    DATA_TYPE = "D";
var proxyMethod = function(instance, methodName, defaultResult) {
    if (!instance[methodName]) {
        instance[methodName] = function() {
            var dataSource = this._dataSource;
            return dataSource ? dataSource[methodName].apply(dataSource, arguments) : defaultResult
        }
    }
};
exports.DataController = Class.inherit(function() {
    function getHeaderItemText(item, description, options) {
        var text = item.text;
        if (commonUtils.isDefined(item.displayText)) {
            text = item.displayText
        } else {
            if (commonUtils.isDefined(item.caption)) {
                text = item.caption
            } else {
                if (item.type === GRAND_TOTAL_TYPE) {
                    text = options.texts.grandTotal
                }
            }
        }
        if (item.isAdditionalTotal) {
            text = stringUtils.format(options.texts.total || "", text)
        }
        return text
    }
    var createHeaderInfo = function() {
        var getHeaderItemsDepth = function(headerItems) {
            var depth = 0;
            foreachTree(headerItems, function(items) {
                depth = math.max(depth, items.length)
            });
            return depth
        };
        var createInfoItem = function(headerItem, breadth, isHorizontal, isTree) {
            var infoItem = {
                type: headerItem.type,
                text: headerItem.text
            };
            if (headerItem.path) {
                infoItem.path = headerItem.path
            }
            if (headerItem.width) {
                infoItem.width = headerItem.width
            }
            if (commonUtils.isDefined(headerItem.wordWrapEnabled)) {
                infoItem.wordWrapEnabled = headerItem.wordWrapEnabled
            }
            if (headerItem.isLast) {
                infoItem.isLast = true
            }
            if (headerItem.sorted) {
                infoItem.sorted = true
            }
            if (headerItem.isMetric) {
                infoItem.dataIndex = headerItem.dataIndex
            }
            if (commonUtils.isDefined(headerItem.expanded)) {
                infoItem.expanded = headerItem.expanded
            }
            if (breadth > 1) {
                infoItem[isHorizontal ? "colspan" : "rowspan"] = breadth
            }
            if (headerItem.depthSize && headerItem.depthSize > 1) {
                infoItem[isHorizontal ? "rowspan" : "colspan"] = headerItem.depthSize
            }
            if (headerItem.index >= 0) {
                infoItem.dataSourceIndex = headerItem.index
            }
            if (isTree && headerItem.children && headerItem.children.length && !headerItem.children[0].isMetric) {
                infoItem.width = null;
                infoItem.isWhiteSpace = true
            }
            return infoItem
        };
        var addInfoItem = function(info, options) {
            var itemInfo, breadth = options.lastIndex - options.index || 1,
                addInfoItemCore = function(info, infoItem, itemIndex, depthIndex, isHorizontal) {
                    var index = isHorizontal ? depthIndex : itemIndex;
                    while (!info[index]) {
                        info.push([])
                    }
                    if (isHorizontal) {
                        info[index].push(infoItem)
                    } else {
                        info[index].unshift(infoItem)
                    }
                };
            itemInfo = createInfoItem(options.headerItem, breadth, options.isHorizontal, options.isTree);
            addInfoItemCore(info, itemInfo, options.index, options.depth, options.isHorizontal);
            if (!options.headerItem.children || 0 === options.headerItem.children.length) {
                return options.lastIndex + 1
            }
            return options.lastIndex
        };
        var isItemSorted = function(items, sortBySummaryPath) {
            var path, item = items[0],
                stringValuesUsed = commonUtils.isString(sortBySummaryPath[0]),
                headerItem = item.dataIndex >= 0 ? items[1] : item;
            if (stringValuesUsed && sortBySummaryPath[0].indexOf("&[") !== -1 && headerItem.key || !headerItem.key) {
                path = createPath(items)
            } else {
                path = $.map(items, function(item) {
                    return item.dataIndex >= 0 ? item.value : item.text
                }).reverse()
            }
            if (item.type === GRAND_TOTAL_TYPE) {
                path = path.slice(1)
            }
            return path.join("/") === sortBySummaryPath.join("/")
        };
        var getViewHeaderItems = function(headerItems, headerDescriptions, cellDescriptions, depthSize, options) {
            var cellDescriptionsCount = cellDescriptions.length,
                viewHeaderItems = options.showData ? createViewHeaderItems(headerItems, headerDescriptions) : [],
                d = $.Deferred();
            when(viewHeaderItems).done(function(viewHeaderItems) {
                options.notifyProgress(.5);
                if (options.showGrandTotals || 0 === headerDescriptions.length) {
                    viewHeaderItems[!options.showTotalsPrior ? "push" : "unshift"]({
                        type: GRAND_TOTAL_TYPE,
                        isEmpty: options.isEmptyGrandTotal
                    })
                }
                if (false !== options.showTotals || "tree" === options.layout) {
                    addAdditionalTotalHeaderItems(viewHeaderItems, headerDescriptions, options.showTotalsPrior, "tree" === options.layout)
                }
                when(foreachTreeAsync(viewHeaderItems, function(items) {
                    var item = items[0];
                    if (!item.children || 0 === item.children.length) {
                        item.depthSize = depthSize - items.length + 1
                    }
                })).done(function() {
                    if (cellDescriptionsCount > 1) {
                        addMetricHeaderItems(viewHeaderItems, cellDescriptions, options.hiddenGrandTotals, options.hiddenTotals)
                    }!options.showEmpty && removeHiddenItems(viewHeaderItems);
                    options.notifyProgress(.75);
                    when(foreachTreeAsync(viewHeaderItems, function(items) {
                        var item = items[0],
                            isMetric = item.isMetric,
                            field = headerDescriptions[items.length - 1] || {};
                        if (item.type === DATA_TYPE && !isMetric) {
                            item.width = field.width
                        }
                        if (isMetric) {
                            item.wordWrapEnabled = cellDescriptions[item.dataIndex].wordWrapEnabled
                        } else {
                            item.wordWrapEnabled = field.wordWrapEnabled
                        }
                        item.isLast = !item.children || !item.children.length;
                        if (item.isLast) {
                            $.each(options.sortBySummaryPaths, function(index, sortBySummaryPath) {
                                if (!commonUtils.isDefined(item.dataIndex)) {
                                    sortBySummaryPath = sortBySummaryPath.slice(0);
                                    sortBySummaryPath.pop()
                                }
                                if (isItemSorted(items, sortBySummaryPath)) {
                                    item.sorted = true;
                                    return false
                                }
                            })
                        }
                        item.text = getHeaderItemText(item, field, options)
                    })).done(function() {
                        if (!viewHeaderItems.length) {
                            viewHeaderItems.push({})
                        }
                        options.notifyProgress(1);
                        d.resolve(viewHeaderItems)
                    })
                })
            });
            return d
        };

        function createHeaderItem(childrenStack, depth, index) {
            var parent = childrenStack[depth] = childrenStack[depth] || [],
                node = parent[index] = {};
            if (childrenStack[depth + 1]) {
                node.children = childrenStack[depth + 1];
                childrenStack.length = depth + 1
            }
            return node
        }

        function createViewHeaderItems(headerItems, headerDescriptions) {
            var headerItem, headerDescriptionsCount = headerDescriptions && headerDescriptions.length || 0,
                childrenStack = [],
                d = $.Deferred();
            when(foreachTreeAsync(headerItems, function(items, index) {
                var item = items[0],
                    path = createPath(items);
                headerItem = createHeaderItem(childrenStack, path.length, index);
                headerItem.type = DATA_TYPE;
                headerItem.value = item.value;
                headerItem.path = path;
                headerItem.text = item.text;
                headerItem.index = item.index;
                headerItem.displayText = item.displayText;
                headerItem.key = item.key;
                headerItem.isEmpty = item.isEmpty;
                if (path.length < headerDescriptionsCount && (!item.children || 0 !== item.children.length)) {
                    headerItem.expanded = !!item.children
                }
            })).done(function() {
                d.resolve(createHeaderItem(childrenStack, 0, 0).children || [])
            });
            return d
        }
        var addMetricHeaderItems = function(headerItems, cellDescriptions, hiddenGrandTotals, hiddenTotals) {
            foreachTree(headerItems, function(items) {
                var i, item = items[0];
                if (!item.children || 0 === item.children.length) {
                    item.children = [];
                    for (i = 0; i < cellDescriptions.length; i++) {
                        var isGrandTotal = item.type === GRAND_TOTAL_TYPE,
                            columnIsHidden = false === cellDescriptions[i].visible || isGrandTotal && $.inArray(i, hiddenGrandTotals) !== -1 || !isGrandTotal && $.inArray(i, hiddenTotals) !== -1;
                        if (columnIsHidden) {
                            continue
                        }
                        item.children.push({
                            caption: cellDescriptions[i].caption,
                            path: item.path,
                            type: item.type,
                            value: i,
                            index: item.index,
                            dataIndex: i,
                            isMetric: true,
                            isEmpty: item.isEmpty && item.isEmpty[i]
                        })
                    }
                }
            })
        };
        var addAdditionalTotalHeaderItems = function(headerItems, headerDescriptions, showTotalsPrior, isTree) {
            showTotalsPrior = showTotalsPrior || isTree;
            foreachTree(headerItems, function(items, index) {
                var item = items[0],
                    parentChildren = (items[1] ? items[1].children : headerItems) || [],
                    dataField = headerDescriptions[items.length - 1];
                if (item.type === DATA_TYPE && item.expanded && (false !== dataField.showTotals || isTree)) {
                    index !== -1 && parentChildren.splice(showTotalsPrior ? index : index + 1, 0, $.extend({}, item, {
                        children: null,
                        type: TOTAL_TYPE,
                        expanded: showTotalsPrior ? true : null,
                        isAdditionalTotal: true
                    }));
                    if (showTotalsPrior) {
                        item.expanded = null
                    }
                }
            })
        };
        var removeEmptyParent = function(items, index) {
            var parent = items[index + 1];
            if (!items[index].children.length && parent && parent.children) {
                parent.children.splice($.inArray(items[index], parent.children), 1);
                removeEmptyParent(items, index + 1)
            }
        };
        var removeHiddenItems = function(headerItems) {
            foreachTree([{
                children: headerItems
            }], function(items, index) {
                var item = items[0],
                    parentChildren = (items[1] ? items[1].children : headerItems) || [];
                if (item && !item.children && (item.isEmpty && item.isEmpty.length ? item.isEmpty[0] : item.isEmpty)) {
                    parentChildren.splice(index, 1);
                    removeEmptyParent(items, 1)
                }
            })
        };
        var fillHeaderInfo = function(info, viewHeaderItems, depthSize, isHorizontal, isTree) {
            var index, depth, lastIndex = 0,
                indexesByDepth = [0];
            foreachTree(viewHeaderItems, function(items) {
                var headerItem = items[0];
                depth = headerItem.isMetric ? depthSize : items.length - 1;
                while (indexesByDepth.length - 1 < depth) {
                    indexesByDepth.push(indexesByDepth[indexesByDepth.length - 1])
                }
                index = indexesByDepth[depth] || 0;
                lastIndex = addInfoItem(info, {
                    headerItem: headerItem,
                    index: index,
                    lastIndex: lastIndex,
                    depth: depth,
                    isHorizontal: isHorizontal,
                    isTree: isTree
                });
                indexesByDepth.length = depth;
                indexesByDepth.push(lastIndex)
            })
        };
        return function(headerItems, headerDescriptions, cellDescriptions, isHorizontal, options) {
            var info = [],
                depthSize = getHeaderItemsDepth(headerItems) || 1,
                d = $.Deferred();
            getViewHeaderItems(headerItems, headerDescriptions, cellDescriptions, depthSize, options).done(function(viewHeaderItems) {
                fillHeaderInfo(info, viewHeaderItems, depthSize, isHorizontal, "tree" === options.layout);
                options.notifyProgress(1);
                d.resolve(info)
            });
            return d
        }
    }();

    function createSortPaths(headerFields, dataFields) {
        var sortBySummaryPaths = [];
        $.each(headerFields, function(index, headerField) {
            var fieldIndex = pivotGridUtils.findField(dataFields, headerField.sortBySummaryField);
            if (fieldIndex >= 0) {
                sortBySummaryPaths.push((headerField.sortBySummaryPath || []).concat([fieldIndex]))
            }
        });
        return sortBySummaryPaths
    }

    function foreachRowInfo(rowsInfo, callback) {
        var columnOffset = 0,
            columnOffsetResetIndexes = [];
        for (var i = 0; i < rowsInfo.length; i++) {
            for (var j = 0; j < rowsInfo[i].length; j++) {
                var rowSpanOffset = (rowsInfo[i][j].rowspan || 1) - 1,
                    visibleIndex = i + rowSpanOffset;
                if (columnOffsetResetIndexes[i]) {
                    columnOffset -= columnOffsetResetIndexes[i];
                    columnOffsetResetIndexes[i] = 0
                }
                if (false === callback(rowsInfo[i][j], visibleIndex, i, j, columnOffset)) {
                    break
                }
                columnOffsetResetIndexes[i + (rowsInfo[i][j].rowspan || 1)] = (columnOffsetResetIndexes[i + (rowsInfo[i][j].rowspan || 1)] || 0) + 1;
                columnOffset++
            }
        }
    }

    function foreachColumnInfo(info, callback, rowIndex, offsets, columnCount, lastProcessedIndexes) {
        rowIndex = rowIndex || 0;
        offsets = offsets || [];
        lastProcessedIndexes = lastProcessedIndexes || [];
        offsets[rowIndex] = offsets[rowIndex] || 0;
        var row = info[rowIndex],
            startIndex = lastProcessedIndexes[rowIndex] + 1 || 0,
            processedColumnCount = 0;
        if (!row) {
            return
        }
        for (var colIndex = startIndex; colIndex < row.length; colIndex++) {
            var cell = row[colIndex],
                visibleIndex = colIndex + offsets[rowIndex],
                colspan = cell.colspan || 1;
            foreachColumnInfo(info, callback, rowIndex + (cell.rowspan || 1), offsets, colspan, lastProcessedIndexes);
            offsets[rowIndex] += colspan - 1;
            processedColumnCount += colspan;
            if (cell.rowspan) {
                for (var i = rowIndex + 1; i < rowIndex + cell.rowspan; i++) {
                    offsets[i] = offsets[i] || 0;
                    offsets[i] += cell.colspan || 1
                }
            }
            if (false === callback(cell, visibleIndex, rowIndex, colIndex)) {
                break
            }
            if (void 0 !== columnCount && processedColumnCount >= columnCount) {
                break
            }
        }
        lastProcessedIndexes[rowIndex] = colIndex
    }

    function createCellsInfo(rowsInfo, columnsInfo, data, dataFields, dataFieldArea) {
        var info = [],
            dataFieldAreaInRows = "row" === dataFieldArea,
            dataSourceCells = data.values;
        dataSourceCells.length && foreachRowInfo(rowsInfo, function(rowInfo, rowIndex) {
            var row = info[rowIndex] = [],
                dataRow = dataSourceCells[rowInfo.dataSourceIndex >= 0 ? rowInfo.dataSourceIndex : data.grandTotalRowIndex] || [];
            rowInfo.isLast && foreachColumnInfo(columnsInfo, function(columnInfo, columnIndex) {
                var dataIndex = (dataFieldAreaInRows ? rowInfo.dataIndex : columnInfo.dataIndex) || 0,
                    dataField = dataFields[dataIndex];
                if (columnInfo.isLast && dataField) {
                    var cellValue, cell = dataRow[columnInfo.dataSourceIndex >= 0 ? columnInfo.dataSourceIndex : data.grandTotalColumnIndex];
                    if (!$.isArray(cell)) {
                        cell = [cell]
                    }
                    cellValue = cell[dataIndex];
                    row[columnIndex] = {
                        text: formatValue(cellValue, dataField),
                        value: cellValue,
                        format: dataField.format,
                        precision: dataField.precision,
                        dataType: dataField.dataType,
                        columnType: columnInfo.type,
                        rowType: rowInfo.type,
                        rowPath: rowInfo.path || [],
                        columnPath: columnInfo.path || [],
                        dataIndex: dataIndex
                    };
                    if (dataField.width) {
                        row[columnIndex].width = dataField.width
                    }
                }
            })
        });
        return info
    }

    function getHeaderIndexedItems(headerItems, maxDepth, options) {
        var visibleIndex = 0,
            indexedItems = [];
        foreachTree(headerItems, function(items) {
            var headerItem = items[0],
                path = createPath(items);
            if (headerItem.children && false === options.showTotals) {
                return
            }
            var indexedItem = $.extend(true, {}, headerItem, {
                visibleIndex: visibleIndex++,
                path: path
            });
            if (commonUtils.isDefined(indexedItem.index)) {
                indexedItems[indexedItem.index] = indexedItem
            } else {
                indexedItems.push(indexedItem)
            }
        });
        return indexedItems
    }

    function createScrollController(dataController, component, dataAdapter) {
        if (component && "virtual" === component.option("scrolling.mode")) {
            return new virtualScrolling.VirtualScrollController(component, $.extend({
                hasKnownLastPage: function() {
                    return true
                },
                pageCount: function() {
                    return math.ceil(this.totalItemsCount() / this.pageSize())
                },
                updateLoading: function() {},
                itemsCount: function() {
                    if (this.pageIndex() < this.pageCount() - 1) {
                        return this.pageSize()
                    } else {
                        this.totalItemsCount() % this.pageSize()
                    }
                },
                items: function() {
                    return []
                },
                viewportItems: function() {
                    return []
                },
                onChanged: function() {},
                isLoading: function() {
                    return dataController.isLoading()
                },
                changingDuration: function() {
                    return dataController._changingDuration || 0
                }
            }, dataAdapter))
        }
    }

    function getHiddenTotals(dataFields) {
        var result = [];
        $.each(dataFields, function(index, field) {
            if (false === field.showTotals) {
                result.push(index)
            }
        });
        return result
    }

    function getHiddenGrandTotalsTotals(dataFields, columnFields) {
        var result = [];
        $.each(dataFields, function(index, field) {
            if (false === field.showGrandTotals) {
                result.push(index)
            }
        });
        if (0 === columnFields.length && result.length === dataFields.length) {
            result = []
        }
        return result
    }
    var members = {
        ctor: function(options) {
            var that = this,
                virtualScrollControllerChanged = $.proxy(that._fireChanged, that);
            options = that._options = options || {};
            that.dataSourceChanged = $.Callbacks();
            that._dataSource = that._createDataSource(options);
            that._rowsScrollController = createScrollController(that, options.component, {
                totalItemsCount: function() {
                    return that.totalRowCount()
                },
                pageIndex: function(index) {
                    return that.rowPageIndex(index)
                },
                pageSize: function() {
                    return that.rowPageSize()
                },
                load: function() {
                    if (that._rowsScrollController.pageIndex() >= this.pageCount()) {
                        that._rowsScrollController.pageIndex(this.pageCount() - 1)
                    }
                    return that._rowsScrollController.handleDataChanged(virtualScrollControllerChanged)
                }
            });
            that._columnsScrollController = createScrollController(that, options.component, {
                totalItemsCount: function() {
                    return that.totalColumnCount()
                },
                pageIndex: function(index) {
                    return that.columnPageIndex(index)
                },
                pageSize: function() {
                    return that.columnPageSize()
                },
                load: function() {
                    if (that._columnsScrollController.pageIndex() >= this.pageCount()) {
                        that._columnsScrollController.pageIndex(this.pageCount() - 1)
                    }
                    return that._columnsScrollController.handleDataChanged(virtualScrollControllerChanged)
                }
            });
            that._stateStoringController = new stateStoring.StateStoringController(options.component).init();
            that._columnsInfo = [];
            that._rowsInfo = [];
            that._cellsInfo = [];
            that.expandValueChanging = $.Callbacks();
            that.loadingChanged = $.Callbacks();
            that.scrollChanged = $.Callbacks();
            that.load();
            that._update();
            that.changed = $.Callbacks()
        },
        _fireChanged: function() {
            var that = this,
                startChanging = new Date;
            that.changed && !that._lockChanged && that.changed.fire();
            that._changingDuration = new Date - startChanging
        },
        load: function() {
            var that = this,
                stateStoringController = this._stateStoringController;
            if (stateStoringController.isEnabled() && !stateStoringController.isLoaded()) {
                stateStoringController.load().always(function(state) {
                    if (state) {
                        that._dataSource.state(state)
                    } else {
                        that._dataSource.load()
                    }
                })
            } else {
                that._dataSource.load()
            }
        },
        calculateVirtualContentParams: function(contentParams) {
            var oldColumnViewportItemSize, oldRowViewportItemSize, newLeftPosition, newTopPosition, that = this,
                rowsScrollController = that._rowsScrollController,
                columnsScrollController = that._columnsScrollController,
                rowViewportItemSize = contentParams.contentHeight / contentParams.rowCount,
                columnViewportItemSize = contentParams.contentWidth / contentParams.columnCount;
            if (rowsScrollController && columnsScrollController) {
                oldColumnViewportItemSize = columnsScrollController.viewportItemSize();
                oldRowViewportItemSize = rowsScrollController.viewportItemSize();
                rowsScrollController.viewportItemSize(rowViewportItemSize);
                columnsScrollController.viewportItemSize(columnViewportItemSize);
                rowsScrollController.viewportSize(contentParams.viewportHeight / rowsScrollController.viewportItemSize());
                rowsScrollController.setContentSize(contentParams.contentHeight);
                columnsScrollController.viewportSize(contentParams.viewportWidth / columnsScrollController.viewportItemSize());
                columnsScrollController.setContentSize(contentParams.contentWidth);
                columnsScrollController.loadIfNeed();
                rowsScrollController.loadIfNeed();
                newLeftPosition = columnsScrollController.getViewportPosition() * columnViewportItemSize / oldColumnViewportItemSize;
                newTopPosition = rowsScrollController.getViewportPosition() * rowViewportItemSize / oldRowViewportItemSize;
                that.setViewportPosition(newLeftPosition, newTopPosition);
                that.scrollChanged.fire({
                    left: newLeftPosition,
                    top: newTopPosition
                });
                return {
                    contentTop: rowsScrollController.getContentOffset(),
                    contentLeft: columnsScrollController.getContentOffset(),
                    width: columnsScrollController.getVirtualContentSize(),
                    height: rowsScrollController.getVirtualContentSize()
                }
            }
        },
        setViewportPosition: function(left, top) {
            this._rowsScrollController.setViewportPosition(top || 0);
            this._columnsScrollController.setViewportPosition(left || 0)
        },
        subscribeToWindowScrollEvents: function($element) {
            this._rowsScrollController && this._rowsScrollController.subscribeToWindowScrollEvents($element)
        },
        updateWindowScrollPosition: function(position) {
            this._rowsScrollController && this._rowsScrollController.scrollTo(position)
        },
        updateViewOptions: function(options) {
            $.extend(this._options, options);
            this._update()
        },
        _handleExpandValueChanging: function(e) {
            this.expandValueChanging.fire(e)
        },
        _handleLoadingChanged: function(isLoading, progress) {
            this.loadingChanged.fire(isLoading, progress)
        },
        _handleFieldsPrepared: function(e) {
            this._options.onFieldsPrepared && this._options.onFieldsPrepared(e)
        },
        _createDataSource: function(options) {
            var dataSource, that = this,
                dataSourceOptions = options.dataSource;
            that._isSharedDataSource = dataSourceOptions instanceof PivotGridDataSource;
            if (that._isSharedDataSource) {
                dataSource = dataSourceOptions
            } else {
                dataSource = new PivotGridDataSource(dataSourceOptions)
            }
            that._expandValueChangingHandler = $.proxy(that, "_handleExpandValueChanging");
            that._loadingChangedHandler = $.proxy(that, "_handleLoadingChanged");
            that._fieldsPreparedHandler = $.proxy(that, "_handleFieldsPrepared");
            that._changedHandler = function() {
                that._update();
                that.dataSourceChanged.fire()
            };
            dataSource.on("changed", that._changedHandler);
            dataSource.on("expandValueChanging", that._expandValueChangingHandler);
            dataSource.on("loadingChanged", that._loadingChangedHandler);
            dataSource.on("fieldsPrepared", that._fieldsPreparedHandler);
            return dataSource
        },
        getDataSource: function() {
            return this._dataSource
        },
        isLoading: function() {
            return this._dataSource.isLoading()
        },
        beginLoading: function() {
            this._dataSource._changeLoadingCount(1)
        },
        endLoading: function() {
            this._dataSource._changeLoadingCount(-1)
        },
        isEmpty: function() {
            var dataFields = this._dataSource.getAreaFields("data"),
                data = this._dataSource.getData();
            return !dataFields.length || !data.values.length
        },
        _update: function() {
            var that = this,
                dataSource = that._dataSource,
                options = that._options,
                columnFields = dataSource.getAreaFields("column"),
                rowFields = dataSource.getAreaFields("row"),
                dataFields = dataSource.getAreaFields("data"),
                dataFieldsForRows = "row" === options.dataFieldArea ? dataFields : [],
                dataFieldsForColumns = "row" !== options.dataFieldArea ? dataFields : [],
                data = dataSource.getData(),
                hiddenTotals = getHiddenTotals(dataFields),
                hiddenGrandTotals = getHiddenGrandTotalsTotals(dataFields, columnFields),
                grandTotalsAreHiddenForNotAllDataFields = dataFields.length > 0 ? hiddenGrandTotals.length !== dataFields.length : true,
                dataIsHiddenForNotAllDataFields = dataFields.length > 0 ? hiddenTotals.length !== dataFields.length : true,
                notifyProgress = function(progress) {
                    this.progress = progress;
                    dataSource._changeLoadingCount(0, .8 + .1 * rowOptions.progress + .1 * columnOptions.progress)
                },
                rowOptions = {
                    isEmptyGrandTotal: data.isEmptyGrandTotalRow,
                    texts: options.texts || {},
                    hiddenTotals: hiddenTotals,
                    hiddenGrandTotals: [],
                    showTotals: options.showRowTotals,
                    showData: dataIsHiddenForNotAllDataFields,
                    showGrandTotals: false !== options.showRowGrandTotals && grandTotalsAreHiddenForNotAllDataFields,
                    sortBySummaryPaths: createSortPaths(columnFields, dataFields),
                    showTotalsPrior: "rows" === options.showTotalsPrior || "both" === options.showTotalsPrior,
                    showEmpty: !options.hideEmptySummaryCells,
                    layout: options.rowHeaderLayout,
                    fields: rowFields,
                    progress: 0,
                    notifyProgress: notifyProgress
                },
                columnOptions = {
                    isEmptyGrandTotal: data.isEmptyGrandTotalColumn,
                    texts: options.texts || {},
                    hiddenTotals: hiddenTotals,
                    showData: dataIsHiddenForNotAllDataFields,
                    hiddenGrandTotals: hiddenGrandTotals,
                    showTotals: options.showColumnTotals,
                    showTotalsPrior: "columns" === options.showTotalsPrior || "both" === options.showTotalsPrior,
                    showGrandTotals: false !== options.showColumnGrandTotals && grandTotalsAreHiddenForNotAllDataFields,
                    sortBySummaryPaths: createSortPaths(rowFields, dataFields),
                    showEmpty: !options.hideEmptySummaryCells,
                    fields: columnFields,
                    progress: 0,
                    notifyProgress: notifyProgress
                };
            if (!commonUtils.isDefined(data.grandTotalRowIndex)) {
                data.grandTotalRowIndex = getHeaderIndexedItems(data.rows, rowFields.length - 1, rowOptions).length
            }
            if (!commonUtils.isDefined(data.grandTotalColumnIndex)) {
                data.grandTotalColumnIndex = getHeaderIndexedItems(data.columns, columnFields.length - 1, columnOptions).length
            }
            dataSource._changeLoadingCount(1, .8);
            when(createHeaderInfo(data.columns, columnFields, dataFieldsForColumns, true, columnOptions), createHeaderInfo(data.rows, rowFields, dataFieldsForRows, false, rowOptions)).done(function(columnsInfo, rowsInfo) {
                that._columnsInfo = columnsInfo;
                that._rowsInfo = rowsInfo;
                if (that._rowsScrollController && that._columnsScrollController && that.changed) {
                    that._rowsScrollController.reset();
                    that._columnsScrollController.reset();
                    that._lockChanged = true;
                    that._rowsScrollController.load();
                    that._columnsScrollController.load();
                    that._lockChanged = false
                }
            }).always(function() {
                dataSource._changeLoadingCount(-1)
            }).done(function() {
                that._fireChanged();
                if (that._stateStoringController.isEnabled() && !that._dataSource.isLoading()) {
                    that._stateStoringController.state(that._dataSource.state());
                    that._stateStoringController.save()
                }
            })
        },
        getRowsInfo: function(getAllData) {
            var rowspan, i, that = this,
                rowsInfo = that._rowsInfo,
                scrollController = that._rowsScrollController;
            if (scrollController && !getAllData) {
                var startIndex = scrollController.beginPageIndex() * that.rowPageSize(),
                    endIndex = scrollController.endPageIndex() * that.rowPageSize() + that.rowPageSize(),
                    newRowsInfo = [],
                    maxDepth = 1;
                foreachRowInfo(rowsInfo, function(rowInfo, visibleIndex, rowIndex, _, columnIndex) {
                    var isVisible = visibleIndex >= startIndex && rowIndex < endIndex,
                        index = rowIndex < startIndex ? 0 : rowIndex - startIndex,
                        cell = rowInfo;
                    if (isVisible) {
                        newRowsInfo[index] = newRowsInfo[index] || [];
                        rowspan = rowIndex < startIndex ? rowInfo.rowspan - (startIndex - rowIndex) || 1 : rowInfo.rowspan;
                        if (startIndex + index + rowspan > endIndex) {
                            rowspan = endIndex - (index + startIndex) || 1
                        }
                        if (rowspan !== rowInfo.rowspan) {
                            cell = $.extend({}, cell, {
                                rowspan: rowspan
                            })
                        }
                        newRowsInfo[index].push(cell);
                        maxDepth = math.max(maxDepth, columnIndex + 1)
                    } else {
                        if (i > endIndex) {
                            return false
                        }
                    }
                });
                foreachRowInfo(newRowsInfo, function(rowInfo, visibleIndex, rowIndex, columnIndex, realColumnIndex) {
                    var colspan = rowInfo.colspan || 1;
                    if (realColumnIndex + colspan > maxDepth) {
                        newRowsInfo[rowIndex][columnIndex] = $.extend({}, rowInfo, {
                            colspan: maxDepth - realColumnIndex || 1
                        })
                    }
                });
                return newRowsInfo
            }
            return rowsInfo
        },
        getColumnsInfo: function(getAllData) {
            var that = this,
                info = that._columnsInfo,
                scrollController = that._columnsScrollController;
            if (scrollController && !getAllData) {
                var startIndex = scrollController.beginPageIndex() * that.columnPageSize(),
                    endIndex = scrollController.endPageIndex() * that.columnPageSize() + that.columnPageSize(),
                    newInfo = [];
                foreachColumnInfo(info, function(columnInfo, visibleIndex, rowIndex) {
                    var colspan, cell = columnInfo,
                        isVisible = visibleIndex + (cell.colspan - 1 || 0) >= startIndex && visibleIndex < endIndex;
                    newInfo[rowIndex] = newInfo[rowIndex] || [];
                    if (isVisible) {
                        if (visibleIndex < startIndex) {
                            colspan = cell.colspan - (startIndex - visibleIndex);
                            visibleIndex = startIndex
                        } else {
                            colspan = cell.colspan
                        }
                        if (visibleIndex + colspan > endIndex) {
                            colspan = endIndex - visibleIndex
                        }
                        if (colspan !== cell.colspan) {
                            cell = $.extend({}, cell, {
                                colspan: colspan
                            })
                        }
                        newInfo[rowIndex].push(cell)
                    } else {
                        if (visibleIndex > endIndex) {
                            return false
                        }
                    }
                });
                info = newInfo
            }
            return info
        },
        totalRowCount: function() {
            return this._rowsInfo.length
        },
        rowPageIndex: function(index) {
            if (void 0 !== index) {
                this._rowPageIndex = index
            }
            return this._rowPageIndex || 0
        },
        totalColumnCount: function() {
            var count = 0;
            if (this._columnsInfo && this._columnsInfo.length) {
                for (var i = 0; i < this._columnsInfo[0].length; i++) {
                    count += this._columnsInfo[0][i].colspan || 1
                }
            }
            return count
        },
        rowPageSize: function(size) {
            if (void 0 !== size) {
                this._rowPageSize = size
            }
            return this._rowPageSize || 20
        },
        columnPageSize: function(size) {
            if (void 0 !== size) {
                this._columnPageSize = size
            }
            return this._columnPageSize || 20
        },
        columnPageIndex: function(index) {
            if (void 0 !== index) {
                this._columnPageIndex = index
            }
            return this._columnPageIndex || 0
        },
        getCellsInfo: function(getAllData) {
            var rowsInfo = this.getRowsInfo(getAllData),
                columnsInfo = this.getColumnsInfo(getAllData),
                data = this._dataSource.getData();
            return createCellsInfo(rowsInfo, columnsInfo, data, this._dataSource.getAreaFields("data"), this._options.dataFieldArea)
        },
        dispose: function() {
            var that = this;
            if (that._isSharedDataSource) {
                that._dataSource.off("changed", that._changedHandler);
                that._dataSource.off("expandValueChanging", that._expandValueChangingHandler);
                that._dataSource.off("loadingChanged", that._loadingChangedHandler)
            } else {
                that._dataSource.dispose()
            }
            that._columnsScrollController && that._columnsScrollController.dispose();
            that._rowsScrollController && that._rowsScrollController.dispose();
            that._stateStoringController.dispose();
            that.expandValueChanging.empty();
            that.changed.empty();
            that.loadingChanged.empty();
            that.scrollChanged.empty();
            that.dataSourceChanged.empty()
        }
    };
    proxyMethod(members, "applyPartialDataSource");
    proxyMethod(members, "collapseHeaderItem");
    proxyMethod(members, "expandHeaderItem");
    proxyMethod(members, "getData");
    return members
}());


text:
<?php
namespace Platformsh\Cli\Command\Environment;

use Platformsh\Cli\Command\CommandBase;
use Platformsh\Cli\Console\ArrayArgument;
use Platformsh\Cli\Util\Wildcard;
use Platformsh\Client\Model\Environment;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class EnvironmentDeleteCommand extends CommandBase
{

    protected function configure()
    {
        $this
            ->setName('environment:delete')
            ->setHiddenAliases(['environment:deactivate'])
            ->setDescription('Delete one or more environments')
            ->addArgument('environment', InputArgument::IS_ARRAY, "The environment(s) to delete.\nThe % character may be used as a wildcard." . "\n" . ArrayArgument::SPLIT_HELP)
            ->addOption('delete-branch', null, InputOption::VALUE_NONE, 'Delete Git branch(es) (inactive environments)')
            ->addOption('no-delete-branch', null, InputOption::VALUE_NONE, 'Do not delete Git branch(es) (inactive environments)')
            ->addOption('type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Delete all environments of a type (adding to any others selected)' . "\n" . ArrayArgument::SPLIT_HELP)
            ->addOption('only-type', 't', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Only delete environment(s) of a specific type' . "\n" . ArrayArgument::SPLIT_HELP)
            ->addOption('exclude', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, "Environment(s) not to delete.\nThe % character may be used as a wildcard.\n" . ArrayArgument::SPLIT_HELP)
            ->addOption('exclude-type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Environment type(s) of which not to delete' . "\n" . ArrayArgument::SPLIT_HELP)
            ->addOption('inactive', null, InputOption::VALUE_NONE, 'Delete all inactive environments (adding to any others selected')
            ->addOption('merged', null, InputOption::VALUE_NONE, 'Delete all merged environments (adding to any others selected)');
        $this->addProjectOption()
             ->addEnvironmentOption()
             ->addWaitOptions();
        $this->addExample('Delete the currently checked out environment');
        $this->addExample('Delete the environments "test" and "example-1"', 'test example-1');
        $this->addExample('Delete all inactive environments', '--inactive');
        $this->addExample('Delete all environments merged with their parent', '--merged');
        $service = $this->config()->get('service.name');
        $this->setHelp(<<<EOF
When a {$service} environment is deleted, it will become "inactive": it will
exist only as a Git branch, containing code but no services, databases nor
files.

This command allows you to delete environment(s) as well as their Git branches.
EOF
        );
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->validateInput($input, true);

        $environments = $this->api()->getEnvironments($this->getSelectedProject());

        /**
         * A list of selected environments, keyed by ID to avoid duplication.
         *
         * @var array<string, Environment> $selectedEnvironments
         */
        $selectedEnvironments = [];
        $error = false;
        $anythingSpecified = false;

        // Add the environment(s) specified in the arguments or options.
        $specifiedEnvironmentIds = ArrayArgument::getArgument($input, 'environment');
        if ($input->getOption('environment')) {
            $specifiedEnvironmentIds = array_merge([$input->getOption('environment')], $specifiedEnvironmentIds);
        }
        if ($specifiedEnvironmentIds) {
            $anythingSpecified = true;
            $allIds = \array_map(function (Environment $e) { return $e->id; }, $environments);
            $specifiedEnvironmentIds = Wildcard::select($allIds, $specifiedEnvironmentIds);
            $notFound = array_diff($specifiedEnvironmentIds, array_keys($environments));
            if (!empty($notFound)) {
                // Refresh the environments list if any environment is not found.
                $environments = $this->api()->getEnvironments($this->getSelectedProject(), true);
                $notFound = array_diff($specifiedEnvironmentIds, array_keys($environments));
            }
            foreach ($notFound as $notFoundId) {
                $this->stdErr->writeln("Environment not found: <error>$notFoundId</error>");
                $error = true;
            }
            $specifiedEnvironments = array_intersect_key($environments, array_flip($specifiedEnvironmentIds));
            $this->stdErr->writeln(count($specifiedEnvironments) . ' environment(s) found by ID');
            $this->stdErr->writeln('');
            foreach ($specifiedEnvironments as $specifiedEnvironment) {
                $selectedEnvironments[$specifiedEnvironment->id] = $specifiedEnvironment;
            }
        }

        // Gather inactive environments.
        if ($input->getOption('inactive')) {
            $anythingSpecified = true;
            if ($input->getOption('no-delete-branch')) {
                $this->stdErr->writeln('The option --no-delete-branch cannot be combined with --inactive.');

                return 1;
            }
            $inactive = array_filter(
                $environments,
                function ($environment) {
                    /** @var Environment $environment */
                    return $environment->status == 'inactive';
                }
            );
            $this->stdErr->writeln(count($inactive) . ' inactive environment(s) found.');
            $this->stdErr->writeln('');
            foreach ($inactive as $inactiveEnv) {
                $selectedEnvironments[$inactiveEnv->id] = $inactiveEnv;
            }
        }

        // Gather merged environments.
        if ($input->getOption('merged')) {
            $anythingSpecified = true;
            $merged = [];
            foreach ($environments as $environment) {
                $merge_info = $environment->getProperty('merge_info', false) ?: [];
                if (isset($environment->parent, $merge_info['commits_ahead'], $merge_info['parent_ref']) && $merge_info['commits_ahead'] === 0) {
                    $selectedEnvironments[$environment->id] = $merged[$environment->id] = $environment;
                }
            }
            $this->stdErr->writeln(count($merged) . ' merged environment(s) found.');
            $this->stdErr->writeln('');
        }

        // Gather environments with the specified --type (can be multiple).
        if ($types = ArrayArgument::getOption($input, 'type')) {
            $anythingSpecified = true;
            $withTypes = [];
            foreach ($environments as $environment) {
                if (\in_array($environment->type, $types)) {
                    $selectedEnvironments[$environment->id] = $withTypes[$environment->id] = $environment;
                }
            }
            $this->stdErr->writeln(count($withTypes) . ' environment(s) found matching type(s): ' . implode(', ', $types));
            $this->stdErr->writeln('');
        }

        // Add the current environment if nothing is otherwise specified.
        if (!$anythingSpecified
            && empty($selectedEnvironments)
            && ($current = $this->getCurrentEnvironment($this->getSelectedProject()))) {
            $this->stdErr->writeln('Nothing specified; selecting the current environment: '. $this->api()->getEnvironmentLabel($current));
            $this->stdErr->writeln('');
            $selectedEnvironments[$current->id] = $current;
        }

        // Exclude environment type(s) specified via --exclude-type or --only-type.
        $excludeTypes = ArrayArgument::getOption($input, 'exclude-type');
        $onlyTypes = ArrayArgument::getOption($input, 'only-type');
        $filtered = \array_filter($selectedEnvironments, function (Environment $environment) use ($excludeTypes, $onlyTypes) {
            if (\in_array($environment->type, $excludeTypes, true)) {
                return false;
            }
            if (!empty($onlyTypes) && !\in_array($environment->type, $onlyTypes, true)) {
                return false;
            }
            return true;
        });
        if (($numExcluded = count($selectedEnvironments) - count($filtered)) > 0) {
            $this->stdErr->writeln($numExcluded . ' environment(s) excluded by type.');
            $this->stdErr->writeln('');
        }
        $selectedEnvironments = $filtered;

        // Exclude environment ID(s) specified in --exclude.
        $excludeIds = ArrayArgument::getOption($input, 'exclude');
        if (!empty($excludeIds)) {
            $resolved = Wildcard::select(\array_keys($selectedEnvironments), $excludeIds);
            if (count($resolved)) {
                $selectedEnvironments = \array_diff_key($selectedEnvironments, \array_flip($resolved));
                $this->stdErr->writeln(count($resolved) . ' environment(s) excluded by ID.');
                $this->stdErr->writeln('');
            }
        }

        if (count($selectedEnvironments)) {
            $this->stdErr->writeln('Selected environment(s): ' . $this->listEnvironments($selectedEnvironments));
            $this->stdErr->writeln('');
        }

        // Confirm which of the environments the user wishes to be deleted.
        $this->api()->sortResources($selectedEnvironments, 'id');
        $toDeleteBranch = [];
        $toDeactivate = [];
        $needNewline = false;
        /** @var \Platformsh\Cli\Service\QuestionHelper $questionHelper */
        $questionHelper = $this->getService('question_helper');
        foreach ($selectedEnvironments as $environment) {
            $environmentId = $environment->id;
            // Check that the environment does not have children.
            // @todo remove this check when Platform's behavior is fixed
            foreach ($environments as $potentialChild) {
                if ($potentialChild->parent === $environment->id) {
                    $this->stdErr->writeln(\sprintf(
                        "The environment %s has children and therefore can't be deleted.",
                        $this->api()->getEnvironmentLabel($environment, 'error')
                    ));
                    $this->stdErr->writeln("Please delete the environment's children first.");
                    $error = $needNewline = true;
                    continue 2;
                }
            }

            if (!\in_array($environment->status, ['active', 'inactive', 'dirty', 'deleting'])) {
                $this->stdErr->writeln("The environment <error>$environmentId</error> has an unrecognised status <error>" . $environment->status . "</error>.");
                $error = $needNewline = true;
                continue;
            }
            if ($environment->status === 'inactive' && $input->getOption('no-delete-branch')) {
                $this->stdErr->writeln("The environment <comment>$environmentId</comment> is inactive and <comment>--no-delete-branch</comment> was specified, so it will not be deleted.");
                $needNewline = true;
                continue;
            }
            if ($environment->status === 'deleting') {
                $this->stdErr->writeln("The environment <comment>$environmentId</comment> is already being deleted.");
                $needNewline = true;
                continue;
            }
            if ($environment->status === 'dirty') {
                $this->stdErr->writeln("The environment <error>$environmentId</error> is currently building, and therefore can't be deleted. Please wait.");
                $error = $needNewline = true;
                continue;
            }

            // Ask about deactivation if the environment is active.
            if ($environment->isActive()) {
                $needNewline = true;
                $this->stdErr->writeln(\sprintf(
                    'The environment %s is currently active: deleting it will delete all associated data.',
                    $this->api()->getEnvironmentLabel($environment, 'comment')
                ));
                if ($questionHelper->confirm('Are you sure you want to delete this environment?')) {
                    $toDeactivate[$environmentId] = $environment;
                } else {
                    $error = true;
                }
            }

            // Ask about deleting the branch, which requires either an inactive
            // environment, or waiting for it to be deactivated.
            if (!$input->getOption('no-delete-branch')
                && ($environment->status === 'inactive' || (isset($toDeactivate[$environmentId]) && $this->shouldWait($input)))) {
                $message = isset($toDeactivate[$environmentId])
                    ? "Delete the inactive environment (Git branch) too?"
                    : "Are you sure you want to delete the inactive environment (Git branch) <comment>$environmentId</comment>?";
                if ($input->getOption('delete-branch') || ($input->isInteractive() && $questionHelper->confirm($message))) {
                    $toDeleteBranch[$environmentId] = $environment;
                } elseif (!isset($toDeactivate[$environmentId])) {
                    $error = true;
                }
                $needNewline = true;
            }
        }

        if ($needNewline) {
            $this->stdErr->writeln('');
        }

        if (empty($toDeleteBranch) && empty($toDeactivate)) {
            $this->stdErr->writeln('No environment(s) to delete.');
            if (!$anythingSpecified) {
                $this->stdErr->writeln(\sprintf('For help, run: <info>%s help environment:delete</info>', $this->config()->get('application.executable')));
            }

            return $error ? 1 : 0;
        }

        $success = $this->deleteMultiple($toDeactivate, $toDeleteBranch, $input) && !$error;

        return $success ? 0 : 1;
    }

    /**
     * @param Environment[] $environments
     *
     * @return string
     */
    private function listEnvironments(array $environments)
    {
        $uniqueIds = \array_unique(\array_map(function(Environment $e) { return $e->id; }, $environments));
        natcasesort($uniqueIds);
        return '<info>' . implode('</info>, <info>', $uniqueIds) . '</info>';
    }

    /**
     * @param array $toDeactivate
     * @param array $toDeleteBranch
     * @param InputInterface $input
     *
     * @return bool
     */
    protected function deleteMultiple(array $toDeactivate, array $toDeleteBranch, InputInterface $input)
    {
        $error = false;
        $deactivateActivities = [];
        $deactivated = 0;
        /** @var Environment $environment */
        foreach ($toDeactivate as $environmentId => $environment) {
            try {
                $this->stdErr->writeln("Deleting environment <info>$environmentId</info>");
                $deactivateActivities[] = $environment->deactivate();
                $deactivated++;
            } catch (\Exception $e) {
                $this->stdErr->writeln($e->getMessage());
            }
        }

        if ($this->shouldWait($input)) {
            /** @var \Platformsh\Cli\Service\ActivityMonitor $activityMonitor */
            $activityMonitor = $this->getService('activity_monitor');
            if (!$activityMonitor->waitMultiple($deactivateActivities, $this->getSelectedProject())) {
                $error = true;
            }
        }

        $deleted = 0;
        foreach ($toDeleteBranch as $environmentId => $environment) {
            try {
                if ($environment->status !== 'inactive') {
                    $environment->refresh();
                    if ($environment->status !== 'inactive') {
                        $this->stdErr->writeln("Cannot delete Git branch <error>$environmentId</error>: the environment is not (yet) inactive.");
                        continue;
                    }
                }
                $environment->delete();
                $this->stdErr->writeln("Deleted Git branch (inactive environment) <info>$environmentId</info>");
                $deleted++;
            } catch (\Exception $e) {
                $this->stdErr->writeln($e->getMessage());
            }
        }

        if ($deleted > 0) {
            $this->stdErr->writeln("Run <info>git fetch --prune</info> to remove deleted branches from your local cache.");
        }

        if ($deleted < count($toDeleteBranch) || $deactivated < count($toDeactivate)) {
            $error = true;
        }

        if (($deleted || $deactivated || $error) && isset($environment)) {
            $this->api()->clearEnvironmentsCache($environment->project);
        }

        return !$error;
    }
}

redpajama_set_name: RedPajamaGithub


text:
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <inttypes.h>
#include <stdint.h>
#include <string.h>

#include <inet/IPAddress.h>
#include <lib/core/DataModelTypes.h>
#include <lib/core/PeerId.h>
#include <lib/support/UnitTestRegistration.h>
#include <transport/raw/PeerAddress.h>

#include <nlunit-test.h>

namespace {

using namespace chip;
using chip::Inet::InterfaceId;
using chip::Inet::IPAddress;
using chip::Transport::PeerAddress;

/**
 *  Test correct identification of IPv6 multicast addresses.
 */
void TestPeerAddressMulticast(nlTestSuite * inSuite, void * inContext)
{
    constexpr chip::FabricId fabric = 0xa1a2a4a8b1b2b4b8;
    constexpr chip::GroupId group   = 0xe10f;
    PeerAddress addr                = PeerAddress::Multicast(fabric, group);
    NL_TEST_ASSERT(inSuite, chip::Transport::Type::kUdp == addr.GetTransportType());
    NL_TEST_ASSERT(inSuite, addr.IsMulticast());

    const Inet::IPAddress & ip = addr.GetIPAddress();
    NL_TEST_ASSERT(inSuite, ip.IsIPv6Multicast());
    NL_TEST_ASSERT(inSuite, chip::Inet::IPAddressType::kIPv6 == ip.Type());

    constexpr uint8_t expected[NL_INET_IPV6_ADDR_LEN_IN_BYTES] = { 0xff, 0x35, 0x00, 0x40, 0xfd, 0xa1, 0xa2, 0xa4,
                                                                   0xa8, 0xb1, 0xb2, 0xb4, 0xb8, 0x00, 0xe1, 0x0f };
    uint8_t result[NL_INET_IPV6_ADDR_LEN_IN_BYTES];
    uint8_t * p = result;
    ip.WriteAddress(p);
    NL_TEST_ASSERT(inSuite, !memcmp(expected, result, NL_INET_IPV6_ADDR_LEN_IN_BYTES));
}

void TestToString(nlTestSuite * inSuite, void * inContext)
{
    char buff[PeerAddress::kMaxToStringSize];
    IPAddress ip;
    {
        IPAddress::FromString("::1", ip);
        PeerAddress::UDP(ip, 1122).ToString(buff);

        NL_TEST_ASSERT(inSuite, !strcmp(buff, "UDP:[::1]:1122"));
    }

    {
        IPAddress::FromString("::1", ip);
        PeerAddress::TCP(ip, 1122).ToString(buff);

        NL_TEST_ASSERT(inSuite, !strcmp(buff, "TCP:[::1]:1122"));
    }

    {
        PeerAddress::BLE().ToString(buff);
        NL_TEST_ASSERT(inSuite, !strcmp(buff, "BLE"));
    }

    {
        IPAddress::FromString("1223::3456:789a", ip);
        PeerAddress::UDP(ip, 8080).ToString(buff);
        // IPV6 does not specify case
        int res1 = strcmp(buff, "UDP:[1223::3456:789a]:8080");
        int res2 = strcmp(buff, "UDP:[1223::3456:789A]:8080");

        NL_TEST_ASSERT(inSuite, (!res1 || !res2));
    }

    {

        PeerAddress udp = PeerAddress(Transport::Type::kUdp);
        udp.SetPort(5840);
        udp.ToString(buff);
        NL_TEST_ASSERT(inSuite, !strcmp(buff, "UDP:[::]:5840"));
    }
}

/**
 *   Test Suite. It lists all the test functions.
 */

// clang-format off
const nlTest sTests[] =
{
    NL_TEST_DEF("PeerAddress Multicast", TestPeerAddressMulticast),
    NL_TEST_DEF("ToString", TestToString),
    NL_TEST_SENTINEL()
};
// clang-format on

} // namespace

int TestPeerAddress(void)
{
    // clang-format off
    nlTestSuite theSuite =
	{
        "PeerAddress",
        &sTests[0],
        nullptr,
        nullptr
    };
    // clang-format on

    // Run test suit againt one context.
    nlTestRunner(&theSuite, nullptr);

    return (nlTestRunnerStats(&theSuite));
}

CHIP_REGISTER_TEST_SUITE(TestPeerAddress)


text:
layout: school_candidate
title: "McKinlay, Elizabeth"
name: "Elizabeth McKinlay"
name_last: "McKinlay"
name_first: "Elizabeth"
name_sortby: "mckinlay"
id: "2468"
ward: "2"
permalink: "/toronto-school-board/elizabeth-mckinlay-2468/"
---


text:
<package>
  <description brief="TFToPathConverter">

     TFToPathConverter

  </description>
  <author>Shanker Keshavdas, Benoit Larochelle</author>
  <license>BSD</license>
  <review status="unreviewed" notes=""/>
  <url></url>
  <depend package="tf"/>
  <depend package="roscpp"/>
  <depend package="geometry_msgs"/>
  <depend package="nav_msgs"/>
  <depend package="visualization_msgs"/>
  <depend package="eclipse_prolog_msgs"/>
</package>


text:
class Decision < ApplicationRecord
  include Checkable
  include HasSimpleImage
  include HasUuid
  include Toggleable

  NAME_LIMIT = 250

  toggleable :active, :visible

  has_many :decision_users, dependent: :delete_all

  validates_presence_of :body, :name
  validates_length_of :name, maximum: NAME_LIMIT

  scope :visible, -> { where(visible: true) }
  scope :recent, -> { order('id desc') }
  scope :list_for_visitors, -> { visible.recent }
  scope :list_for_administration, -> { recent }

  def self.entity_parameters
    %i[active body end_date name simple_image_id visible]
  end

  # @param [Hash] list
  def add_answers(list)
    new_answers = {}
    list.each do |answer_uuid, answer_text|
      next if answer_text.blank?

      new_answers[answer_uuid] = answer_text
    end

    self.answers = new_answers
    save
  end

  # @param [String] answer_uuid
  def answer_count(answer_uuid)
    decision_users.where(answer: answer_uuid).count
  end

  # @param [User] user
  def voted?(user)
    decision_users.owned_by(user).exists?
  end

  # @param [User] user
  # @param [String] answer_uuid
  def add_vote(user, answer_uuid)
    return if voted?(user)

    decision_users.owned_by(user).create(answer: answer_uuid)
  end

  # @param [User] user
  def remove_vote(user)
    decision_users.owned_by(user).delete_all
  end

  # @param [String] answer_uuid
  def percent(answer_uuid)
    vote_count = decision_users.count
    answer_count(answer_uuid).to_f / vote_count * 100
  end
end


text:
package com.tinkerpop.blueprints.pgm.impls.rexster.util;

import com.tinkerpop.blueprints.pgm.Element;
import com.tinkerpop.blueprints.pgm.impls.rexster.RexsterGraph;
import com.tinkerpop.blueprints.pgm.impls.rexster.RexsterTokens;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;

/**
 * @author Marko A. Rodriguez (http://markorodriguez.com)
 */
public abstract class RexsterElementSequence<T extends Element> implements Iterable<T>, Iterator<T> {

    protected final int bufferSize = 100;
    protected int start = 0;
    protected int end = bufferSize;

    protected final Queue<T> queue = new LinkedList<T>();
    protected final RexsterGraph graph;
    protected final String uri;

    public RexsterElementSequence(final String uri, final RexsterGraph graph) {
        this.graph = graph;
        this.uri = uri;
        this.fillBuffer();
    }

    public boolean hasNext() {
        if (!queue.isEmpty())
            return true;
        else {
            fillBuffer();
            return !queue.isEmpty();
        }
    }

    public T next() {
        if (!queue.isEmpty()) {
            return queue.remove();
        } else {
            fillBuffer();
            if (!queue.isEmpty()) {
                return queue.remove();
            } else
                throw new NoSuchElementException();
        }
    }

    public Iterator<T> iterator() {
        return this;
    }

    public void remove() {
        throw new UnsupportedOperationException();
    }

    protected abstract void fillBuffer();

    protected String createSeparator() {
        if (this.uri.contains(RexsterTokens.QUESTION))
            return RexsterTokens.AND;
        else
            return RexsterTokens.QUESTION;
    }
}


text:
namespace mk
{
  namespace renderer
  {
    namespace mesh
    {
      template <typename T> RectPatch<T>::RectPatch()
      : mVao(),
        mVertices(),
        mWidth(0),
        mHeight(0)
      {
      }

      template <typename T> RectPatch<T>::RectPatch(int size)
      : RectPatch(size, size)
      {
      }

      template <typename T> RectPatch<T>::RectPatch(int width, int height)
      : mVao(),
        mVertices(width * height),
        mWidth(width),
        mHeight(height)
      {
        recreate();
      }

      template <typename T> RectPatch<T>::RectPatch(RectPatch<T>&& rectPatch)
      {
        mVao = std::move(rectPatch.mVao);
        mVertices = std::move(rectPatch.mVertices);
        mWidth = rectPatch.mWidth;
        mHeight = rectPatch.mHeight;

        rectPatch.mWidth = 0;
        rectPatch.mHeight = 0;
      }

      template <typename T> RectPatch<T>& RectPatch<T>::operator=(RectPatch<T>&& rectPatch)
      {
        mVao = std::move(rectPatch.mVao);
        mVertices = std::move(rectPatch.mVertices);
        mWidth = rectPatch.mWidth;
        mHeight = rectPatch.mHeight;

        rectPatch.mWidth = 0;
        rectPatch.mHeight = 0;

        return *this;
      }

      template <typename T> int RectPatch<T>::getWidth()
      {
        return mWidth;
      }

      template <typename T> int RectPatch<T>::getHeight()
      {
        return mHeight;
      }

      template <typename T> void RectPatch<T>::resize(int width, int height)
      {
        if (mVao)
        {
          mVao.reset();
        }

        mVertices.resize(width * height);
        mWidth = width;
        mHeight = height;

        recreate();
      }

      template <typename T> const T* RectPatch<T>::data()
      {
        return !mVertices.empty() ? mVertices.data() : nullptr;
      }

      template <typename T> typename RectPatch<T>::Accessor RectPatch<T>::operator[](int row)
      {
        return Accessor(mVertices.data() + row * mWidth);
      }

      template <typename T> void RectPatch<T>::computeNormals()
      {
        for (int i = 0; i < mHeight; ++i)
        for (int j = 0; j < mWidth; ++j)
        {
          const int index = i * mWidth + j;

          const glm::vec3 left = (0 == j) ? mVertices[index].mPos : mVertices[index - 1].mPos;
          const glm::vec3 right = (mWidth - 1 == j) ? mVertices[index].mPos : mVertices[index + 1].mPos;
          const glm::vec3 top = (0 == i) ? mVertices[index].mPos : mVertices[(i - 1) * mWidth + j].mPos;
          const glm::vec3 bottom = (mHeight - 1 == i) ? mVertices[index].mPos : mVertices[(i + 1) * mWidth + j].mPos;

          mVertices[index].mNormal = glm::normalize(glm::cross(bottom - top, right - left));
        }
      }

      template <typename T> void RectPatch<T>::refreshGPU()
      {
        mVao->bind();
        mVao->refreshData(0, mVertices.data(), mVertices.size());
      }

      template <typename T> void RectPatch<T>::render()
      {
        const int nIndices = mWidth * mHeight + (mWidth + 1) * (mHeight - 2);

        mVao->bind();
        mVao->render(GL_TRIANGLE_STRIP, nIndices);
      }

      template <typename T> gl::Vao<T>& RectPatch<T>::getVao()
      {
        assert(mVao && "Called getVao on an unsized RectPatch");
        return *mVao.get();
      }

      template <typename T> void RectPatch<T>::recreate()
      {
        int n = mWidth;
        int m = mHeight;

        float N = static_cast<float>(n) - 1.0f;
        float M = static_cast<float>(m) - 1.0f;

        for (int i = 0; i < m; ++i)
        for (int j = 0; j < n; ++j)
        {
          mVertices[i * n + j].mPos = glm::vec3(static_cast<float>(j) - N * 0.5f,
                                                0.0f,
                                                static_cast<float>(i) - M * 0.5f);
        }

        computeNormals();

        std::vector<unsigned int> indices(n * m + (n + 1) * (m - 2));

        int index = 0;

        for (int i = 0; i < m - 1; ++i)
        for (int j = 0; j < n; ++j)
        {
          int isEvenRow = (i % 2 == 0);
          int column = j * isEvenRow + (n - 1 - j) * (1 - isEvenRow);
          int row = i * isEvenRow + (i + 1) * (1 - isEvenRow);
          int next = isEvenRow * 2 - 1;

          indices[index++] = static_cast<unsigned int>(row * n + column);
          indices[index++] = static_cast<unsigned int>((row + next) * n + column);

          if (j == (n - 1) && i < (m - 2))
          {
            indices[index++] = static_cast<unsigned int>((row + isEvenRow) * n + column);
          }
        }

        mVao.reset(new gl::Vao<T>(mVertices, indices, GL_DYNAMIC_DRAW));
      }

      template class RectPatch<VertexPN>;
      template class RectPatch<VertexPNT>;
    }
  }
}


text:
#include "apr_buckets.h"
#define APR_WANT_MEMFUNC
#include "apr_want.h"

static apr_status_t heap_bucket_read(apr_bucket *b, const char **str,
                                     apr_size_t *len, apr_read_type_e block)
{
    apr_bucket_heap *h = b->data;

    *str = h->base + b->start;
    *len = b->length;
    return APR_SUCCESS;
}

static void heap_bucket_destroy(void *data)
{
    apr_bucket_heap *h = data;

    if (apr_bucket_shared_destroy(h)) {
        (*h->free_func)(h->base);
        apr_bucket_free(h);
    }
}

/* Warning: if you change this function, be sure to
 * change apr_bucket_pool_make() too! */
APU_DECLARE(apr_bucket *) apr_bucket_heap_make(apr_bucket *b, const char *buf,
                                               apr_size_t length,
                                               void (*free_func)(void *data))
{
    apr_bucket_heap *h;

    h = apr_bucket_alloc(sizeof(*h), b->list);

    if (!free_func) {
        h->alloc_len = length;
        h->base = apr_bucket_alloc(h->alloc_len, b->list);
        if (h->base == NULL) {
            apr_bucket_free(h);
            return NULL;
        }
        h->free_func = apr_bucket_free;
        memcpy(h->base, buf, length);
    }
    else {
        /* XXX: we lose the const qualifier here which indicates
         * there's something screwy with the API...
         */
        h->base = (char *) buf;
        h->alloc_len = length;
        h->free_func = free_func;
    }

    b = apr_bucket_shared_make(b, h, 0, length);
    b->type = &apr_bucket_type_heap;

    return b;
}

APU_DECLARE(apr_bucket *) apr_bucket_heap_create(const char *buf,
                                                 apr_size_t length,
                                                 void (*free_func)(void *data),
                                                 apr_bucket_alloc_t *list)
{
    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);

    APR_BUCKET_INIT(b);
    b->free = apr_bucket_free;
    b->list = list;
    return apr_bucket_heap_make(b, buf, length, free_func);
}

APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_heap = {
    "HEAP", 5, APR_BUCKET_DATA,
    heap_bucket_destroy,
    heap_bucket_read,
    apr_bucket_setaside_noop,
    apr_bucket_shared_split,
    apr_bucket_shared_copy
};


text:
if test -d tmp/historical/; then
  rm -rf tmp/historical/
fi
mkdir -p tmp/historical/
cd tmp/historical/
git init
echo "hi" > file
git add file
git commit --allow-empty -m "Initial commit"

# Work on and build our historical branch
git checkout -b feature
echo "hello" > file
git add file
git commit -m "Added hello file"
echo "world" > file2
git add file2
git commit -m "Added world file"

# Generate squashed branch for our PR
# DEV: We use -B to overwrite any past squashed branches
git checkout -B feature.squashed master
git merge --squash feature
git commit -m "Added hello and world files"

# Push our squashed branch and open PR for `feature.squashed` to `master`
git push origin feature.squashed


text:
package org.apache.cassandra.db.filter;

import java.nio.ByteBuffer;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.IColumnContainer;
import org.apache.cassandra.db.Memtable;
import org.apache.cassandra.db.SuperColumn;
import org.apache.cassandra.db.columniterator.IColumnIterator;
import org.apache.cassandra.db.columniterator.IdentityQueryFilter;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.io.util.FileDataInput;
import org.apache.cassandra.thrift.SlicePredicate;
import org.apache.cassandra.thrift.SliceRange;
import org.apache.cassandra.utils.ReducingIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QueryFilter
{
    private static Logger logger = LoggerFactory.getLogger(QueryFilter.class);

    public final DecoratedKey key;
    public final QueryPath path;
    public final IFilter filter;
    private final IFilter superFilter;

    public QueryFilter(DecoratedKey key, QueryPath path, IFilter filter)
    {
        this.key = key;
        this.path = path;
        this.filter = filter;
        superFilter = path.superColumnName == null ? null : new NamesQueryFilter(path.superColumnName);
    }

    public IColumnIterator getMemtableColumnIterator(Memtable memtable, AbstractType comparator)
    {
        ColumnFamily cf = memtable.getColumnFamily(key);
        if (cf == null)
            return null;
        return getMemtableColumnIterator(cf, key, comparator);
    }

    public IColumnIterator getMemtableColumnIterator(ColumnFamily cf, DecoratedKey key, AbstractType comparator)
    {
        assert cf != null;
        if (path.superColumnName == null)
            return filter.getMemtableColumnIterator(cf, key, comparator);
        return superFilter.getMemtableColumnIterator(cf, key, comparator);
    }

    // TODO move gcBefore into a field
    public IColumnIterator getSSTableColumnIterator(SSTableReader sstable)
    {
        if (path.superColumnName == null)
            return filter.getSSTableColumnIterator(sstable, key);
        return superFilter.getSSTableColumnIterator(sstable, key);
    }

    public IColumnIterator getSSTableColumnIterator(SSTableReader sstable, FileDataInput file, DecoratedKey key)
    {
        if (path.superColumnName == null)
            return filter.getSSTableColumnIterator(sstable.metadata, file, key);
        return superFilter.getSSTableColumnIterator(sstable.metadata, file, key);
    }

    // here so it can be used by SQF and NQF.  non-package callers should call IFilter.getColumnComparator
    static Comparator<IColumn> getColumnComparator(final Comparator<ByteBuffer> comparator)
    {
        return new Comparator<IColumn>()
        {
            public int compare(IColumn c1, IColumn c2)
            {
                return comparator.compare(c1.name(), c2.name());
            }
        };
    }

    public void collectCollatedColumns(final ColumnFamily returnCF, Iterator<IColumn> collatedColumns, final int gcBefore)
    {
        // define a 'reduced' iterator that merges columns w/ the same name, which
        // greatly simplifies computing liveColumns in the presence of tombstones.
        ReducingIterator<IColumn, IColumn> reduced = new ReducingIterator<IColumn, IColumn>(collatedColumns)
        {
            ColumnFamily curCF = returnCF.cloneMeShallow();

            protected boolean isEqual(IColumn o1, IColumn o2)
            {
                return o1.name().equals(o2.name());
            }

            public void reduce(IColumn current)
            {
                curCF.addColumn(current);
            }

            protected IColumn getReduced()
            {
                IColumn c = curCF.getSortedColumns().iterator().next();
                if (superFilter != null)
                {
                    // filterSuperColumn only looks at immediate parent (the supercolumn) when determining if a subcolumn
                    // is still live, i.e., not shadowed by the parent's tombstone.  so, bump it up temporarily to the tombstone
                    // time of the cf, if that is greater.
                    long deletedAt = c.getMarkedForDeleteAt();
                    if (returnCF.getMarkedForDeleteAt() > deletedAt)
                        ((SuperColumn)c).markForDeleteAt(c.getLocalDeletionTime(), returnCF.getMarkedForDeleteAt());

                    c = filter.filterSuperColumn((SuperColumn)c, gcBefore);
                    ((SuperColumn)c).markForDeleteAt(c.getLocalDeletionTime(), deletedAt); // reset sc tombstone time to what it should be
                }
                curCF.clear();

                return c;
            }
        };

        (superFilter == null ? filter : superFilter).collectReducedColumns(returnCF, reduced, gcBefore);
    }

    public String getColumnFamilyName()
    {
        return path.columnFamilyName;
    }

    public static boolean isRelevant(IColumn column, IColumnContainer container, int gcBefore)
    {
        // the column itself must be not gc-able (it is live, or a still relevant tombstone, or has live subcolumns), (1)
        // and if its container is deleted, the column must be changed more recently than the container tombstone (2)
        // (since otherwise, the only thing repair cares about is the container tombstone)
        long maxChange = column.mostRecentLiveChangeAt();
        return (!column.isMarkedForDelete() || column.getLocalDeletionTime() > gcBefore || maxChange > column.getMarkedForDeleteAt()) // (1)
               && (!container.isMarkedForDelete() || maxChange > container.getMarkedForDeleteAt()); // (2)
    }

    /**
     * @return a QueryFilter object to satisfy the given slice criteria:  @param key the row to slice
     * @param path path to the level to slice at (CF or SuperColumn)
     * @param start column to start slice at, inclusive; empty for "the first column"
     * @param finish column to stop slice at, inclusive; empty for "the last column"
     * @param reversed true to start with the largest column (as determined by configured sort order) instead of smallest
     * @param limit maximum number of non-deleted columns to return
     */
    public static QueryFilter getSliceFilter(DecoratedKey key, QueryPath path, ByteBuffer start, ByteBuffer finish, boolean reversed, int limit)
    {
        return new QueryFilter(key, path, new SliceQueryFilter(start, finish, reversed, limit));
    }

    /**
     * return a QueryFilter object that includes every column in the row.
     * This is dangerous on large rows; avoid except for test code.
     */
    public static QueryFilter getIdentityFilter(DecoratedKey key, QueryPath path)
    {
        return new QueryFilter(key, path, new IdentityQueryFilter());
    }

    /**
     * @return a QueryFilter object that will return columns matching the given names
     * @param key the row to slice
     * @param path path to the level to slice at (CF or SuperColumn)
     * @param columns the column names to restrict the results to
     */
    public static QueryFilter getNamesFilter(DecoratedKey key, QueryPath path, SortedSet<ByteBuffer> columns)
    {
        return new QueryFilter(key, path, new NamesQueryFilter(columns));
    }

    public static IFilter getFilter(SlicePredicate predicate, AbstractType comparator)
    {
        if (predicate.column_names != null)
        {
            final SortedSet<ByteBuffer> columnNameSet = new TreeSet<ByteBuffer>(comparator);
            columnNameSet.addAll(predicate.column_names);
            return new NamesQueryFilter(columnNameSet);
        }

        SliceRange range = predicate.slice_range;
        return new SliceQueryFilter(range.start, range.finish, range.reversed, range.count);
    }

    /**
     * convenience method for creating a name filter matching a single column
     */
    public static QueryFilter getNamesFilter(DecoratedKey key, QueryPath path, ByteBuffer column)
    {
        return new QueryFilter(key, path, new NamesQueryFilter(column));
    }
}


text:
'use strict'

import * as types from 'Core/actions/Scenes/actionTypes'
import {
    expect
} from 'chai'
import reducer from './data'

describe('scenes data reducer', () => {
    it('should return the initial state', () => {
        expect(reducer(undefined, {})).to.deep.equal([])
    })

    it('should handle ADD_SCENE', () => {
        const data = {
            name: 'hoge',
            events: []
        }
        const action = {
            type: types.ADD_SCENE,
            data
        }
        expect(reducer([], action)).to.deep.equal([data])
    })
})


text:
<?xml version="1.0" encoding="utf-8"?>
<com.mobimvp.privacybox.ui.widgets.WeightedLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.mobimvp.privacybox"
    android:id="@+id/parentPanel"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingLeft="10dip"
    android:paddingRight="10dip"
    android:paddingTop="9dip"
    app:majorWeight="0.65"
    app:minorWeight="1" >

    <LinearLayout
        android:id="@+id/topPanel"
        android:layout_width="fill_parent"
        android:layout_height="48dip"
        android:orientation="vertical" >

        <LinearLayout
            android:id="@+id/title_template"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingLeft="15dip"
            android:paddingRight="15dip" >

            <ImageView
                android:id="@+id/icon"
                android:layout_width="24dip"
                android:layout_height="24dip"
                android:layout_gravity="top"
                android:paddingRight="10dip"
                android:scaleType="fitCenter" />

            <TextView
                android:id="@+id/alertTitle"
                style="@style/DialogWindowTitle"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:singleLine="true"
                android:textAppearance="@style/TextAppearance.Large" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/contentPanel"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical" >

        <ScrollView
            android:id="@+id/scrollView"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dip"
            android:layout_marginLeft="15dip"
            android:layout_marginRight="15dip"
            android:layout_marginTop="20dip" >

            <TextView
                android:id="@+id/message"
                style="@style/TextAppearance.Medium"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </ScrollView>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/customPanel"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" >

        <FrameLayout
            android:id="@+id/custom"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </FrameLayout>

    <LinearLayout
        android:id="@+id/buttonPanel"
        android:layout_width="fill_parent"
        android:layout_height="68dip"
        android:orientation="vertical"
        android:paddingTop="20dip" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingBottom="6dip"
            android:paddingLeft="8dip"
            android:paddingRight="8dip"
            android:paddingTop="6dip" >

            <Button
                android:id="@+id/button1"
                style="@style/Button.Dialog.Ok"
                android:layout_width="0dip"
                android:layout_height="44dip"
                android:layout_gravity="left"
                android:layout_weight="1"
                android:maxLines="2" />

            <View
                android:id="@+id/view1"
                android:layout_width="8dip"
                android:layout_height="1px"
                android:visibility="gone" />

            <Button
                android:id="@+id/button3"
                style="@style/Button.Dialog"
                android:layout_width="0dip"
                android:layout_height="44dip"
                android:layout_gravity="center_horizontal"
                android:layout_weight="1"
                android:maxLines="2" />

            <View
                android:id="@+id/view2"
                android:layout_width="8dip"
                android:layout_height="1px"
                android:visibility="gone" />
            <!-- android:background="@drawable/dialog_btn_interval"/> -->

            <Button
                android:id="@+id/button2"
                style="@style/Button.Dialog.Cancel"
                android:layout_width="0dip"
                android:layout_height="44dip"
                android:layout_gravity="right"
                android:layout_weight="1"
                android:maxLines="2" />
        </LinearLayout>
    </LinearLayout>

</com.mobimvp.privacybox.ui.widgets.WeightedLinearLayout>