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

/* global Float64Array, Int32Array, Uint32Array, Uint16Array */

/**
 * List for data storage
 * @module echarts/data/List
 */
import { __DEV__ } from '../config';
import * as zrUtil from 'zrender/src/core/util';
import Model from '../model/Model';
import DataDiffer from './DataDiffer';
import Source from './Source';
import { defaultDimValueGetters, DefaultDataProvider } from './helper/dataProvider';
import { summarizeDimensions } from './helper/dimensionHelper';
var isObject = zrUtil.isObject;
var UNDEFINED = 'undefined';
var INDEX_NOT_FOUND = -1; // Use prefix to avoid index to be the same as otherIdList[idx],
// which will cause weird udpate animation.

var ID_PREFIX = 'e\0\0';
var dataCtors = {
  'float': typeof Float64Array === UNDEFINED ? Array : Float64Array,
  'int': typeof Int32Array === UNDEFINED ? Array : Int32Array,
  // Ordinal data type can be string or int
  'ordinal': Array,
  'number': Array,
  'time': Array
}; // Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is
// different from the Ctor of typed array.

var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array;
var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array;
var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array;

function getIndicesCtor(list) {
  // The possible max value in this._indicies is always this._rawCount despite of filtering.
  return list._rawCount > 65535 ? CtorUint32Array : CtorUint16Array;
}

function cloneChunk(originalChunk) {
  var Ctor = originalChunk.constructor; // Only shallow clone is enough when Array.

  return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk);
}

var TRANSFERABLE_PROPERTIES = ['hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', '_rawData', '_chunkSize', '_chunkCount', '_dimValueGetter', '_count', '_rawCount', '_nameDimIdx', '_idDimIdx'];
var CLONE_PROPERTIES = ['_extent', '_approximateExtent', '_rawExtent'];

function transferProperties(target, source) {
  zrUtil.each(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) {
    if (source.hasOwnProperty(propName)) {
      target[propName] = source[propName];
    }
  });
  target.__wrappedMethods = source.__wrappedMethods;
  zrUtil.each(CLONE_PROPERTIES, function (propName) {
    target[propName] = zrUtil.clone(source[propName]);
  });
  target._calculationInfo = zrUtil.extend(source._calculationInfo);
}
/**
 * @constructor
 * @alias module:echarts/data/List
 *
 * @param {Array.<string|Object>} dimensions
 *      For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
 *      Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
 *      Spetial fields: {
 *          ordinalMeta: <module:echarts/data/OrdinalMeta>
 *          createInvertedIndices: <boolean>
 *      }
 * @param {module:echarts/model/Model} hostModel
 */


var List = function (dimensions, hostModel) {
  dimensions = dimensions || ['x', 'y'];
  var dimensionInfos = {};
  var dimensionNames = [];
  var invertedIndicesMap = {};

  for (var i = 0; i < dimensions.length; i++) {
    // Use the original dimensions[i], where other flag props may exists.
    var dimensionInfo = dimensions[i];

    if (zrUtil.isString(dimensionInfo)) {
      dimensionInfo = {
        name: dimensionInfo
      };
    }

    var dimensionName = dimensionInfo.name;
    dimensionInfo.type = dimensionInfo.type || 'float';

    if (!dimensionInfo.coordDim) {
      dimensionInfo.coordDim = dimensionName;
      dimensionInfo.coordDimIndex = 0;
    }

    dimensionInfo.otherDims = dimensionInfo.otherDims || {};
    dimensionNames.push(dimensionName);
    dimensionInfos[dimensionName] = dimensionInfo;
    dimensionInfo.index = i;

    if (dimensionInfo.createInvertedIndices) {
      invertedIndicesMap[dimensionName] = [];
    }
  }
  /**
   * @readOnly
   * @type {Array.<string>}
   */


  this.dimensions = dimensionNames;
  /**
   * Infomation of each data dimension, like data type.
   * @type {Object}
   */

  this._dimensionInfos = dimensionInfos;
  /**
   * @type {module:echarts/model/Model}
   */

  this.hostModel = hostModel;
  /**
   * @type {module:echarts/model/Model}
   */

  this.dataType;
  /**
   * Indices stores the indices of data subset after filtered.
   * This data subset will be used in chart.
   * @type {Array.<number>}
   * @readOnly
   */

  this._indices = null;
  this._count = 0;
  this._rawCount = 0;
  /**
   * Data storage
   * @type {Object.<key, Array.<TypedArray|Array>>}
   * @private
   */

  this._storage = {};
  /**
   * @type {Array.<string>}
   */

  this._nameList = [];
  /**
   * @type {Array.<string>}
   */

  this._idList = [];
  /**
   * Models of data option is stored sparse for optimizing memory cost
   * @type {Array.<module:echarts/model/Model>}
   * @private
   */

  this._optionModels = [];
  /**
   * Global visual properties after visual coding
   * @type {Object}
   * @private
   */

  this._visual = {};
  /**
   * Globel layout properties.
   * @type {Object}
   * @private
   */

  this._layout = {};
  /**
   * Item visual properties after visual coding
   * @type {Array.<Object>}
   * @private
   */

  this._itemVisuals = [];
  /**
   * Key: visual type, Value: boolean
   * @type {Object}
   * @readOnly
   */

  this.hasItemVisual = {};
  /**
   * Item layout properties after layout
   * @type {Array.<Object>}
   * @private
   */

  this._itemLayouts = [];
  /**
   * Graphic elemnents
   * @type {Array.<module:zrender/Element>}
   * @private
   */

  this._graphicEls = [];
  /**
   * Max size of each chunk.
   * @type {number}
   * @private
   */

  this._chunkSize = 1e5;
  /**
   * @type {number}
   * @private
   */

  this._chunkCount = 0;
  /**
   * @type {Array.<Array|Object>}
   * @private
   */

  this._rawData;
  /**
   * Raw extent will not be cloned, but only transfered.
   * It will not be calculated util needed.
   * key: dim,
   * value: {end: number, extent: Array.<number>}
   * @type {Object}
   * @private
   */

  this._rawExtent = {};
  /**
   * @type {Object}
   * @private
   */

  this._extent = {};
  /**
   * key: dim
   * value: extent
   * @type {Object}
   * @private
   */

  this._approximateExtent = {};
  /**
   * Cache summary info for fast visit. See "dimensionHelper".
   * @type {Object}
   * @private
   */

  this._dimensionsSummary = summarizeDimensions(this);
  /**
   * @type {Object.<Array|TypedArray>}
   * @private
   */

  this._invertedIndicesMap = invertedIndicesMap;
  /**
   * @type {Object}
   * @private
   */

  this._calculationInfo = {};
  /**
   * User output info of this data.
   * DO NOT use it in other places!
   *
   * When preparing user params for user callbacks, we have
   * to clone these inner data structures to prevent users
   * from modifying them to effect built-in logic. And for
   * performance consideration we make this `userOutput` to
   * avoid clone them too many times.
   *
   * @type {Object}
   * @readOnly
   */

  this.userOutput = this._dimensionsSummary.userOutput;
};

var listProto = List.prototype;
listProto.type = 'list';
/**
 * If each data item has it's own option
 * @type {boolean}
 */

listProto.hasItemOption = true;
/**
 * The meanings of the input parameter `dim`:
 *
 * + If dim is a number (e.g., `1`), it means the index of the dimension.
 *   For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'.
 * + If dim is a number-like string (e.g., `"1"`):
 *     + If there is the same concrete dim name defined in `this.dimensions`, it means that concrete name.
 *     + If not, it will be converted to a number, which means the index of the dimension.
 *        (why? because of the backward compatbility. We have been tolerating number-like string in
 *        dimension setting, although now it seems that it is not a good idea.)
 *     For example, `visualMap[i].dimension: "1"` is the same meaning as `visualMap[i].dimension: 1`,
 *     if no dimension name is defined as `"1"`.
 * + If dim is a not-number-like string, it means the concrete dim name.
 *   For example, it can be be default name `"x"`, `"y"`, `"z"`, `"lng"`, `"lat"`, `"angle"`, `"radius"`,
 *   or customized in `dimensions` property of option like `"age"`.
 *
 * Get dimension name
 * @param {string|number} dim See above.
 * @return {string} Concrete dim name.
 */

listProto.getDimension = function (dim) {
  if (typeof dim === 'number' // If being a number-like string but not being defined a dimension name.
  || !isNaN(dim) && !this._dimensionInfos.hasOwnProperty(dim)) {
    dim = this.dimensions[dim];
  }

  return dim;
};
/**
 * Get type and calculation info of particular dimension
 * @param {string|number} dim
 *        Dimension can be concrete names like x, y, z, lng, lat, angle, radius
 *        Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
 */


listProto.getDimensionInfo = function (dim) {
  // Do not clone, because there may be categories in dimInfo.
  return this._dimensionInfos[this.getDimension(dim)];
};
/**
 * @return {Array.<string>} concrete dimension name list on coord.
 */


listProto.getDimensionsOnCoord = function () {
  return this._dimensionsSummary.dataDimsOnCoord.slice();
};
/**
 * @param {string} coordDim
 * @param {number} [idx] A coordDim may map to more than one data dim.
 *        If idx is `true`, return a array of all mapped dims.
 *        If idx is not specified, return the first dim not extra.
 * @return {string|Array.<string>} concrete data dim.
 *        If idx is number, and not found, return null/undefined.
 *        If idx is `true`, and not found, return empty array (always return array).
 */


listProto.mapDimension = function (coordDim, idx) {
  var dimensionsSummary = this._dimensionsSummary;

  if (idx == null) {
    return dimensionsSummary.encodeFirstDimNotExtra[coordDim];
  }

  var dims = dimensionsSummary.encode[coordDim];
  return idx === true // always return array if idx is `true`
  ? (dims || []).slice() : dims && dims[idx];
};
/**
 * Initialize from data
 * @param {Array.<Object|number|Array>} data source or data or data provider.
 * @param {Array.<string>} [nameLIst] The name of a datum is used on data diff and
 *        defualt label/tooltip.
 *        A name can be specified in encode.itemName,
 *        or dataItem.name (only for series option data),
 *        or provided in nameList from outside.
 * @param {Function} [dimValueGetter] (dataItem, dimName, dataIndex, dimIndex) => number
 */


listProto.initData = function (data, nameList, dimValueGetter) {
  var notProvider = Source.isInstance(data) || zrUtil.isArrayLike(data);

  if (notProvider) {
    data = new DefaultDataProvider(data, this.dimensions.length);
  }

  this._rawData = data; // Clear

  this._storage = {};
  this._indices = null;
  this._nameList = nameList || [];
  this._idList = [];
  this._nameRepeatCount = {};

  if (!dimValueGetter) {
    this.hasItemOption = false;
  }
  /**
   * @readOnly
   */


  this.defaultDimValueGetter = defaultDimValueGetters[this._rawData.getSource().sourceFormat]; // Default dim value getter

  this._dimValueGetter = dimValueGetter = dimValueGetter || this.defaultDimValueGetter;
  this._dimValueGetterArrayRows = defaultDimValueGetters.arrayRows; // Reset raw extent.

  this._rawExtent = {};

  this._initDataFromProvider(0, data.count()); // If data has no item option.


  if (data.pure) {
    this.hasItemOption = false;
  }
};

listProto.getProvider = function () {
  return this._rawData;
};
/**
 * Caution: Can be only called on raw data (before `this._indices` created).
 */


listProto.appendData = function (data) {
  var rawData = this._rawData;
  var start = this.count();
  rawData.appendData(data);
  var end = rawData.count();

  if (!rawData.persistent) {
    end += start;
  }

  this._initDataFromProvider(start, end);
};
/**
 * Caution: Can be only called on raw data (before `this._indices` created).
 * This method does not modify `rawData` (`dataProvider`), but only
 * add values to storage.
 *
 * The final count will be increased by `Math.max(values.length, names.length)`.
 *
 * @param {Array.<Array.<*>>} values That is the SourceType: 'arrayRows', like
 *        [
 *            [12, 33, 44],
 *            [NaN, 43, 1],
 *            ['-', 'asdf', 0]
 *        ]
 *        Each item is exaclty cooresponding to a dimension.
 * @param {Array.<string>} [names]
 */


listProto.appendValues = function (values, names) {
  var chunkSize = this._chunkSize;
  var storage = this._storage;
  var dimensions = this.dimensions;
  var dimLen = dimensions.length;
  var rawExtent = this._rawExtent;
  var start = this.count();
  var end = start + Math.max(values.length, names ? names.length : 0);
  var originalChunkCount = this._chunkCount;

  for (var i = 0; i < dimLen; i++) {
    var dim = dimensions[i];

    if (!rawExtent[dim]) {
      rawExtent[dim] = getInitialExtent();
    }

    if (!storage[dim]) {
      storage[dim] = [];
    }

    prepareChunks(storage, this._dimensionInfos[dim], chunkSize, originalChunkCount, end);
    this._chunkCount = storage[dim].length;
  }

  var emptyDataItem = new Array(dimLen);

  for (var idx = start; idx < end; idx++) {
    var sourceIdx = idx - start;
    var chunkIndex = Math.floor(idx / chunkSize);
    var chunkOffset = idx % chunkSize; // Store the data by dimensions

    for (var k = 0; k < dimLen; k++) {
      var dim = dimensions[k];

      var val = this._dimValueGetterArrayRows(values[sourceIdx] || emptyDataItem, dim, sourceIdx, k);

      storage[dim][chunkIndex][chunkOffset] = val;
      var dimRawExtent = rawExtent[dim];
      val < dimRawExtent[0] && (dimRawExtent[0] = val);
      val > dimRawExtent[1] && (dimRawExtent[1] = val);
    }

    if (names) {
      this._nameList[idx] = names[sourceIdx];
    }
  }

  this._rawCount = this._count = end; // Reset data extent

  this._extent = {};
  prepareInvertedIndex(this);
};

listProto._initDataFromProvider = function (start, end) {
  // Optimize.
  if (start >= end) {
    return;
  }

  var chunkSize = this._chunkSize;
  var rawData = this._rawData;
  var storage = this._storage;
  var dimensions = this.dimensions;
  var dimLen = dimensions.length;
  var dimensionInfoMap = this._dimensionInfos;
  var nameList = this._nameList;
  var idList = this._idList;
  var rawExtent = this._rawExtent;
  var nameRepeatCount = this._nameRepeatCount = {};
  var nameDimIdx;
  var originalChunkCount = this._chunkCount;

  for (var i = 0; i < dimLen; i++) {
    var dim = dimensions[i];

    if (!rawExtent[dim]) {
      rawExtent[dim] = getInitialExtent();
    }

    var dimInfo = dimensionInfoMap[dim];

    if (dimInfo.otherDims.itemName === 0) {
      nameDimIdx = this._nameDimIdx = i;
    }

    if (dimInfo.otherDims.itemId === 0) {
      this._idDimIdx = i;
    }

    if (!storage[dim]) {
      storage[dim] = [];
    }

    prepareChunks(storage, dimInfo, chunkSize, originalChunkCount, end);
    this._chunkCount = storage[dim].length;
  }

  var dataItem = new Array(dimLen);

  for (var idx = start; idx < end; idx++) {
    // NOTICE: Try not to write things into dataItem
    dataItem = rawData.getItem(idx, dataItem); // Each data item is value
    // [1, 2]
    // 2
    // Bar chart, line chart which uses category axis
    // only gives the 'y' value. 'x' value is the indices of category
    // Use a tempValue to normalize the value to be a (x, y) value

    var chunkIndex = Math.floor(idx / chunkSize);
    var chunkOffset = idx % chunkSize; // Store the data by dimensions

    for (var k = 0; k < dimLen; k++) {
      var dim = dimensions[k];
      var dimStorage = storage[dim][chunkIndex]; // PENDING NULL is empty or zero

      var val = this._dimValueGetter(dataItem, dim, idx, k);

      dimStorage[chunkOffset] = val;
      var dimRawExtent = rawExtent[dim];
      val < dimRawExtent[0] && (dimRawExtent[0] = val);
      val > dimRawExtent[1] && (dimRawExtent[1] = val);
    } // ??? FIXME not check by pure but sourceFormat?
    // TODO refactor these logic.


    if (!rawData.pure) {
      var name = nameList[idx];

      if (dataItem && name == null) {
        // If dataItem is {name: ...}, it has highest priority.
        // That is appropriate for many common cases.
        if (dataItem.name != null) {
          // There is no other place to persistent dataItem.name,
          // so save it to nameList.
          nameList[idx] = name = dataItem.name;
        } else if (nameDimIdx != null) {
          var nameDim = dimensions[nameDimIdx];
          var nameDimChunk = storage[nameDim][chunkIndex];

          if (nameDimChunk) {
            name = nameDimChunk[chunkOffset];
            var ordinalMeta = dimensionInfoMap[nameDim].ordinalMeta;

            if (ordinalMeta && ordinalMeta.categories.length) {
              name = ordinalMeta.categories[name];
            }
          }
        }
      } // Try using the id in option
      // id or name is used on dynamical data, mapping old and new items.


      var id = dataItem == null ? null : dataItem.id;

      if (id == null && name != null) {
        // Use name as id and add counter to avoid same name
        nameRepeatCount[name] = nameRepeatCount[name] || 0;
        id = name;

        if (nameRepeatCount[name] > 0) {
          id += '__ec__' + nameRepeatCount[name];
        }

        nameRepeatCount[name]++;
      }

      id != null && (idList[idx] = id);
    }
  }

  if (!rawData.persistent && rawData.clean) {
    // Clean unused data if data source is typed array.
    rawData.clean();
  }

  this._rawCount = this._count = end; // Reset data extent

  this._extent = {};
  prepareInvertedIndex(this);
};

function prepareChunks(storage, dimInfo, chunkSize, chunkCount, end) {
  var DataCtor = dataCtors[dimInfo.type];
  var lastChunkIndex = chunkCount - 1;
  var dim = dimInfo.name;
  var resizeChunkArray = storage[dim][lastChunkIndex];

  if (resizeChunkArray && resizeChunkArray.length < chunkSize) {
    var newStore = new DataCtor(Math.min(end - lastChunkIndex * chunkSize, chunkSize)); // The cost of the copy is probably inconsiderable
    // within the initial chunkSize.

    for (var j = 0; j < resizeChunkArray.length; j++) {
      newStore[j] = resizeChunkArray[j];
    }

    storage[dim][lastChunkIndex] = newStore;
  } // Create new chunks.


  for (var k = chunkCount * chunkSize; k < end; k += chunkSize) {
    storage[dim].push(new DataCtor(Math.min(end - k, chunkSize)));
  }
}

function prepareInvertedIndex(list) {
  var invertedIndicesMap = list._invertedIndicesMap;
  zrUtil.each(invertedIndicesMap, function (invertedIndices, dim) {
    var dimInfo = list._dimensionInfos[dim]; // Currently, only dimensions that has ordinalMeta can create inverted indices.

    var ordinalMeta = dimInfo.ordinalMeta;

    if (ordinalMeta) {
      invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length); // The default value of TypedArray is 0. To avoid miss
      // mapping to 0, we should set it as INDEX_NOT_FOUND.

      for (var i = 0; i < invertedIndices.length; i++) {
        invertedIndices[i] = INDEX_NOT_FOUND;
      }

      for (var i = 0; i < list._count; i++) {
        // Only support the case that all values are distinct.
        invertedIndices[list.get(dim, i)] = i;
      }
    }
  });
}

function getRawValueFromStore(list, dimIndex, rawIndex) {
  var val;

  if (dimIndex != null) {
    var chunkSize = list._chunkSize;
    var chunkIndex = Math.floor(rawIndex / chunkSize);
    var chunkOffset = rawIndex % chunkSize;
    var dim = list.dimensions[dimIndex];
    var chunk = list._storage[dim][chunkIndex];

    if (chunk) {
      val = chunk[chunkOffset];
      var ordinalMeta = list._dimensionInfos[dim].ordinalMeta;

      if (ordinalMeta && ordinalMeta.categories.length) {
        val = ordinalMeta.categories[val];
      }
    }
  }

  return val;
}
/**
 * @return {number}
 */


listProto.count = function () {
  return this._count;
};

listProto.getIndices = function () {
  var newIndices;
  var indices = this._indices;

  if (indices) {
    var Ctor = indices.constructor;
    var thisCount = this._count; // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`.

    if (Ctor === Array) {
      newIndices = new Ctor(thisCount);

      for (var i = 0; i < thisCount; i++) {
        newIndices[i] = indices[i];
      }
    } else {
      newIndices = new Ctor(indices.buffer, 0, thisCount);
    }
  } else {
    var Ctor = getIndicesCtor(this);
    var newIndices = new Ctor(this.count());

    for (var i = 0; i < newIndices.length; i++) {
      newIndices[i] = i;
    }
  }

  return newIndices;
};
/**
 * Get value. Return NaN if idx is out of range.
 * @param {string} dim Dim must be concrete name.
 * @param {number} idx
 * @param {boolean} stack
 * @return {number}
 */


listProto.get = function (dim, idx
/*, stack */
) {
  if (!(idx >= 0 && idx < this._count)) {
    return NaN;
  }

  var storage = this._storage;

  if (!storage[dim]) {
    // TODO Warn ?
    return NaN;
  }

  idx = this.getRawIndex(idx);
  var chunkIndex = Math.floor(idx / this._chunkSize);
  var chunkOffset = idx % this._chunkSize;
  var chunkStore = storage[dim][chunkIndex];
  var value = chunkStore[chunkOffset]; // FIXME ordinal data type is not stackable
  // if (stack) {
  //     var dimensionInfo = this._dimensionInfos[dim];
  //     if (dimensionInfo && dimensionInfo.stackable) {
  //         var stackedOn = this.stackedOn;
  //         while (stackedOn) {
  //             // Get no stacked data of stacked on
  //             var stackedValue = stackedOn.get(dim, idx);
  //             // Considering positive stack, negative stack and empty data
  //             if ((value >= 0 && stackedValue > 0)  // Positive stack
  //                 || (value <= 0 && stackedValue < 0) // Negative stack
  //             ) {
  //                 value += stackedValue;
  //             }
  //             stackedOn = stackedOn.stackedOn;
  //         }
  //     }
  // }

  return value;
};
/**
 * @param {string} dim concrete dim
 * @param {number} rawIndex
 * @return {number|string}
 */


listProto.getByRawIndex = function (dim, rawIdx) {
  if (!(rawIdx >= 0 && rawIdx < this._rawCount)) {
    return NaN;
  }

  var dimStore = this._storage[dim];

  if (!dimStore) {
    // TODO Warn ?
    return NaN;
  }

  var chunkIndex = Math.floor(rawIdx / this._chunkSize);
  var chunkOffset = rawIdx % this._chunkSize;
  var chunkStore = dimStore[chunkIndex];
  return chunkStore[chunkOffset];
};
/**
 * FIXME Use `get` on chrome maybe slow(in filterSelf and selectRange).
 * Hack a much simpler _getFast
 * @private
 */


listProto._getFast = function (dim, rawIdx) {
  var chunkIndex = Math.floor(rawIdx / this._chunkSize);
  var chunkOffset = rawIdx % this._chunkSize;
  var chunkStore = this._storage[dim][chunkIndex];
  return chunkStore[chunkOffset];
};
/**
 * Get value for multi dimensions.
 * @param {Array.<string>} [dimensions] If ignored, using all dimensions.
 * @param {number} idx
 * @return {number}
 */


listProto.getValues = function (dimensions, idx
/*, stack */
) {
  var values = [];

  if (!zrUtil.isArray(dimensions)) {
    // stack = idx;
    idx = dimensions;
    dimensions = this.dimensions;
  }

  for (var i = 0, len = dimensions.length; i < len; i++) {
    values.push(this.get(dimensions[i], idx
    /*, stack */
    ));
  }

  return values;
};
/**
 * If value is NaN. Inlcuding '-'
 * Only check the coord dimensions.
 * @param {string} dim
 * @param {number} idx
 * @return {number}
 */


listProto.hasValue = function (idx) {
  var dataDimsOnCoord = this._dimensionsSummary.dataDimsOnCoord;

  for (var i = 0, len = dataDimsOnCoord.length; i < len; i++) {
    // Ordinal type originally can be string or number.
    // But when an ordinal type is used on coord, it can
    // not be string but only number. So we can also use isNaN.
    if (isNaN(this.get(dataDimsOnCoord[i], idx))) {
      return false;
    }
  }

  return true;
};
/**
 * Get extent of data in one dimension
 * @param {string} dim
 * @param {boolean} stack
 */


listProto.getDataExtent = function (dim
/*, stack */
) {
  // Make sure use concrete dim as cache name.
  dim = this.getDimension(dim);
  var dimData = this._storage[dim];
  var initialExtent = getInitialExtent(); // stack = !!((stack || false) && this.getCalculationInfo(dim));

  if (!dimData) {
    return initialExtent;
  } // Make more strict checkings to ensure hitting cache.


  var currEnd = this.count(); // var cacheName = [dim, !!stack].join('_');
  // var cacheName = dim;
  // Consider the most cases when using data zoom, `getDataExtent`
  // happened before filtering. We cache raw extent, which is not
  // necessary to be cleared and recalculated when restore data.

  var useRaw = !this._indices; // && !stack;

  var dimExtent;

  if (useRaw) {
    return this._rawExtent[dim].slice();
  }

  dimExtent = this._extent[dim];

  if (dimExtent) {
    return dimExtent.slice();
  }

  dimExtent = initialExtent;
  var min = dimExtent[0];
  var max = dimExtent[1];

  for (var i = 0; i < currEnd; i++) {
    // var value = stack ? this.get(dim, i, true) : this._getFast(dim, this.getRawIndex(i));
    var value = this._getFast(dim, this.getRawIndex(i));

    value < min && (min = value);
    value > max && (max = value);
  }

  dimExtent = [min, max];
  this._extent[dim] = dimExtent;
  return dimExtent;
};
/**
 * Optimize for the scenario that data is filtered by a given extent.
 * Consider that if data amount is more than hundreds of thousand,
 * extent calculation will cost more than 10ms and the cache will
 * be erased because of the filtering.
 */


listProto.getApproximateExtent = function (dim
/*, stack */
) {
  dim = this.getDimension(dim);
  return this._approximateExtent[dim] || this.getDataExtent(dim
  /*, stack */
  );
};

listProto.setApproximateExtent = function (extent, dim
/*, stack */
) {
  dim = this.getDimension(dim);
  this._approximateExtent[dim] = extent.slice();
};
/**
 * @param {string} key
 * @return {*}
 */


listProto.getCalculationInfo = function (key) {
  return this._calculationInfo[key];
};
/**
 * @param {string|Object} key or k-v object
 * @param {*} [value]
 */


listProto.setCalculationInfo = function (key, value) {
  isObject(key) ? zrUtil.extend(this._calculationInfo, key) : this._calculationInfo[key] = value;
};
/**
 * Get sum of data in one dimension
 * @param {string} dim
 */


listProto.getSum = function (dim
/*, stack */
) {
  var dimData = this._storage[dim];
  var sum = 0;

  if (dimData) {
    for (var i = 0, len = this.count(); i < len; i++) {
      var value = this.get(dim, i
      /*, stack */
      );

      if (!isNaN(value)) {
        sum += value;
      }
    }
  }

  return sum;
};
/**
 * Get median of data in one dimension
 * @param {string} dim
 */


listProto.getMedian = function (dim
/*, stack */
) {
  var dimDataArray = []; // map all data of one dimension

  this.each(dim, function (val, idx) {
    if (!isNaN(val)) {
      dimDataArray.push(val);
    }
  }); // TODO
  // Use quick select?
  // immutability & sort

  var sortedDimDataArray = [].concat(dimDataArray).sort(function (a, b) {
    return a - b;
  });
  var len = this.count(); // calculate median

  return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2;
}; // /**
//  * Retreive the index with given value
//  * @param {string} dim Concrete dimension.
//  * @param {number} value
//  * @return {number}
//  */
// Currently incorrect: should return dataIndex but not rawIndex.
// Do not fix it until this method is to be used somewhere.
// FIXME Precision of float value
// listProto.indexOf = function (dim, value) {
//     var storage = this._storage;
//     var dimData = storage[dim];
//     var chunkSize = this._chunkSize;
//     if (dimData) {
//         for (var i = 0, len = this.count(); i < len; i++) {
//             var chunkIndex = Math.floor(i / chunkSize);
//             var chunkOffset = i % chunkSize;
//             if (dimData[chunkIndex][chunkOffset] === value) {
//                 return i;
//             }
//         }
//     }
//     return -1;
// };

/**
 * Only support the dimension which inverted index created.
 * Do not support other cases until required.
 * @param {string} concrete dim
 * @param {number|string} value
 * @return {number} rawIndex
 */


listProto.rawIndexOf = function (dim, value) {
  var invertedIndices = dim && this._invertedIndicesMap[dim];
  var rawIndex = invertedIndices[value];

  if (rawIndex == null || isNaN(rawIndex)) {
    return INDEX_NOT_FOUND;
  }

  return rawIndex;
};
/**
 * Retreive the index with given name
 * @param {number} idx
 * @param {number} name
 * @return {number}
 */


listProto.indexOfName = function (name) {
  for (var i = 0, len = this.count(); i < len; i++) {
    if (this.getName(i) === name) {
      return i;
    }
  }

  return -1;
};
/**
 * Retreive the index with given raw data index
 * @param {number} idx
 * @param {number} name
 * @return {number}
 */


listProto.indexOfRawIndex = function (rawIndex) {
  if (!this._indices) {
    return rawIndex;
  }

  if (rawIndex >= this._rawCount || rawIndex < 0) {
    return -1;
  } // Indices are ascending


  var indices = this._indices; // If rawIndex === dataIndex

  var rawDataIndex = indices[rawIndex];

  if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) {
    return rawIndex;
  }

  var left = 0;
  var right = this._count - 1;

  while (left <= right) {
    var mid = (left + right) / 2 | 0;

    if (indices[mid] < rawIndex) {
      left = mid + 1;
    } else if (indices[mid] > rawIndex) {
      right = mid - 1;
    } else {
      return mid;
    }
  }

  return -1;
};
/**
 * Retreive the index of nearest value
 * @param {string} dim
 * @param {number} value
 * @param {number} [maxDistance=Infinity]
 * @return {Array.<number>} Considere multiple points has the same value.
 */


listProto.indicesOfNearest = function (dim, value, maxDistance) {
  var storage = this._storage;
  var dimData = storage[dim];
  var nearestIndices = [];

  if (!dimData) {
    return nearestIndices;
  }

  if (maxDistance == null) {
    maxDistance = Infinity;
  }

  var minDist = Number.MAX_VALUE;
  var minDiff = -1;

  for (var i = 0, len = this.count(); i < len; i++) {
    var diff = value - this.get(dim, i
    /*, stack */
    );
    var dist = Math.abs(diff);

    if (diff <= maxDistance && dist <= minDist) {
      // For the case of two data are same on xAxis, which has sequence data.
      // Show the nearest index
      // https://github.com/ecomfe/echarts/issues/2869
      if (dist < minDist || diff >= 0 && minDiff < 0) {
        minDist = dist;
        minDiff = diff;
        nearestIndices.length = 0;
      }

      nearestIndices.push(i);
    }
  }

  return nearestIndices;
};
/**
 * Get raw data index
 * @param {number} idx
 * @return {number}
 */


listProto.getRawIndex = getRawIndexWithoutIndices;

function getRawIndexWithoutIndices(idx) {
  return idx;
}

function getRawIndexWithIndices(idx) {
  if (idx < this._count && idx >= 0) {
    return this._indices[idx];
  }

  return -1;
}
/**
 * Get raw data item
 * @param {number} idx
 * @return {number}
 */


listProto.getRawDataItem = function (idx) {
  if (!this._rawData.persistent) {
    var val = [];

    for (var i = 0; i < this.dimensions.length; i++) {
      var dim = this.dimensions[i];
      val.push(this.get(dim, idx));
    }

    return val;
  } else {
    return this._rawData.getItem(this.getRawIndex(idx));
  }
};
/**
 * @param {number} idx
 * @param {boolean} [notDefaultIdx=false]
 * @return {string}
 */


listProto.getName = function (idx) {
  var rawIndex = this.getRawIndex(idx);
  return this._nameList[rawIndex] || getRawValueFromStore(this, this._nameDimIdx, rawIndex) || '';
};
/**
 * @param {number} idx
 * @param {boolean} [notDefaultIdx=false]
 * @return {string}
 */


listProto.getId = function (idx) {
  return getId(this, this.getRawIndex(idx));
};

function getId(list, rawIndex) {
  var id = list._idList[rawIndex];

  if (id == null) {
    id = getRawValueFromStore(list, list._idDimIdx, rawIndex);
  }

  if (id == null) {
    // FIXME Check the usage in graph, should not use prefix.
    id = ID_PREFIX + rawIndex;
  }

  return id;
}

function normalizeDimensions(dimensions) {
  if (!zrUtil.isArray(dimensions)) {
    dimensions = [dimensions];
  }

  return dimensions;
}

function validateDimensions(list, dims) {
  for (var i = 0; i < dims.length; i++) {
    // stroage may be empty when no data, so use
    // dimensionInfos to check.
    if (!list._dimensionInfos[dims[i]]) {
      console.error('Unkown dimension ' + dims[i]);
    }
  }
}
/**
 * Data iteration
 * @param {string|Array.<string>}
 * @param {Function} cb
 * @param {*} [context=this]
 *
 * @example
 *  list.each('x', function (x, idx) {});
 *  list.each(['x', 'y'], function (x, y, idx) {});
 *  list.each(function (idx) {})
 */


listProto.each = function (dims, cb, context, contextCompat) {
  'use strict';

  if (!this._count) {
    return;
  }

  if (typeof dims === 'function') {
    contextCompat = context;
    context = cb;
    cb = dims;
    dims = [];
  } // contextCompat just for compat echarts3


  context = context || contextCompat || this;
  dims = zrUtil.map(normalizeDimensions(dims), this.getDimension, this);
  var dimSize = dims.length;

  for (var i = 0; i < this.count(); i++) {
    // Simple optimization
    switch (dimSize) {
      case 0:
        cb.call(context, i);
        break;

      case 1:
        cb.call(context, this.get(dims[0], i), i);
        break;

      case 2:
        cb.call(context, this.get(dims[0], i), this.get(dims[1], i), i);
        break;

      default:
        var k = 0;
        var value = [];

        for (; k < dimSize; k++) {
          value[k] = this.get(dims[k], i);
        } // Index


        value[k] = i;
        cb.apply(context, value);
    }
  }
};
/**
 * Data filter
 * @param {string|Array.<string>}
 * @param {Function} cb
 * @param {*} [context=this]
 */


listProto.filterSelf = function (dimensions, cb, context, contextCompat) {
  'use strict';

  if (!this._count) {
    return;
  }

  if (typeof dimensions === 'function') {
    contextCompat = context;
    context = cb;
    cb = dimensions;
    dimensions = [];
  } // contextCompat just for compat echarts3


  context = context || contextCompat || this;
  dimensions = zrUtil.map(normalizeDimensions(dimensions), this.getDimension, this);
  var count = this.count();
  var Ctor = getIndicesCtor(this);
  var newIndices = new Ctor(count);
  var value = [];
  var dimSize = dimensions.length;
  var offset = 0;
  var dim0 = dimensions[0];

  for (var i = 0; i < count; i++) {
    var keep;
    var rawIdx = this.getRawIndex(i); // Simple optimization

    if (dimSize === 0) {
      keep = cb.call(context, i);
    } else if (dimSize === 1) {
      var val = this._getFast(dim0, rawIdx);

      keep = cb.call(context, val, i);
    } else {
      for (var k = 0; k < dimSize; k++) {
        value[k] = this._getFast(dim0, rawIdx);
      }

      value[k] = i;
      keep = cb.apply(context, value);
    }

    if (keep) {
      newIndices[offset++] = rawIdx;
    }
  } // Set indices after filtered.


  if (offset < count) {
    this._indices = newIndices;
  }

  this._count = offset; // Reset data extent

  this._extent = {};
  this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
  return this;
};
/**
 * Select data in range. (For optimization of filter)
 * (Manually inline code, support 5 million data filtering in data zoom.)
 */


listProto.selectRange = function (range) {
  'use strict';

  if (!this._count) {
    return;
  }

  var dimensions = [];

  for (var dim in range) {
    if (range.hasOwnProperty(dim)) {
      dimensions.push(dim);
    }
  }

  var dimSize = dimensions.length;

  if (!dimSize) {
    return;
  }

  var originalCount = this.count();
  var Ctor = getIndicesCtor(this);
  var newIndices = new Ctor(originalCount);
  var offset = 0;
  var dim0 = dimensions[0];
  var min = range[dim0][0];
  var max = range[dim0][1];
  var quickFinished = false;

  if (!this._indices) {
    // Extreme optimization for common case. About 2x faster in chrome.
    var idx = 0;

    if (dimSize === 1) {
      var dimStorage = this._storage[dimensions[0]];

      for (var k = 0; k < this._chunkCount; k++) {
        var chunkStorage = dimStorage[k];
        var len = Math.min(this._count - k * this._chunkSize, this._chunkSize);

        for (var i = 0; i < len; i++) {
          var val = chunkStorage[i]; // NaN will not be filtered. Consider the case, in line chart, empty
          // value indicates the line should be broken. But for the case like
          // scatter plot, a data item with empty value will not be rendered,
          // but the axis extent may be effected if some other dim of the data
          // item has value. Fortunately it is not a significant negative effect.

          if (val >= min && val <= max || isNaN(val)) {
            newIndices[offset++] = idx;
          }

          idx++;
        }
      }

      quickFinished = true;
    } else if (dimSize === 2) {
      var dimStorage = this._storage[dim0];
      var dimStorage2 = this._storage[dimensions[1]];
      var min2 = range[dimensions[1]][0];
      var max2 = range[dimensions[1]][1];

      for (var k = 0; k < this._chunkCount; k++) {
        var chunkStorage = dimStorage[k];
        var chunkStorage2 = dimStorage2[k];
        var len = Math.min(this._count - k * this._chunkSize, this._chunkSize);

        for (var i = 0; i < len; i++) {
          var val = chunkStorage[i];
          var val2 = chunkStorage2[i]; // Do not filter NaN, see comment above.

          if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) {
            newIndices[offset++] = idx;
          }

          idx++;
        }
      }

      quickFinished = true;
    }
  }

  if (!quickFinished) {
    if (dimSize === 1) {
      for (var i = 0; i < originalCount; i++) {
        var rawIndex = this.getRawIndex(i);

        var val = this._getFast(dim0, rawIndex); // Do not filter NaN, see comment above.


        if (val >= min && val <= max || isNaN(val)) {
          newIndices[offset++] = rawIndex;
        }
      }
    } else {
      for (var i = 0; i < originalCount; i++) {
        var keep = true;
        var rawIndex = this.getRawIndex(i);

        for (var k = 0; k < dimSize; k++) {
          var dimk = dimensions[k];

          var val = this._getFast(dim, rawIndex); // Do not filter NaN, see comment above.


          if (val < range[dimk][0] || val > range[dimk][1]) {
            keep = false;
          }
        }

        if (keep) {
          newIndices[offset++] = this.getRawIndex(i);
        }
      }
    }
  } // Set indices after filtered.


  if (offset < originalCount) {
    this._indices = newIndices;
  }

  this._count = offset; // Reset data extent

  this._extent = {};
  this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
  return this;
};
/**
 * Data mapping to a plain array
 * @param {string|Array.<string>} [dimensions]
 * @param {Function} cb
 * @param {*} [context=this]
 * @return {Array}
 */


listProto.mapArray = function (dimensions, cb, context, contextCompat) {
  'use strict';

  if (typeof dimensions === 'function') {
    contextCompat = context;
    context = cb;
    cb = dimensions;
    dimensions = [];
  } // contextCompat just for compat echarts3


  context = context || contextCompat || this;
  var result = [];
  this.each(dimensions, function () {
    result.push(cb && cb.apply(this, arguments));
  }, context);
  return result;
}; // Data in excludeDimensions is copied, otherwise transfered.


function cloneListForMapAndSample(original, excludeDimensions) {
  var allDimensions = original.dimensions;
  var list = new List(zrUtil.map(allDimensions, original.getDimensionInfo, original), original.hostModel); // FIXME If needs stackedOn, value may already been stacked

  transferProperties(list, original);
  var storage = list._storage = {};
  var originalStorage = original._storage; // Init storage

  for (var i = 0; i < allDimensions.length; i++) {
    var dim = allDimensions[i];

    if (originalStorage[dim]) {
      // Notice that we do not reset invertedIndicesMap here, becuase
      // there is no scenario of mapping or sampling ordinal dimension.
      if (zrUtil.indexOf(excludeDimensions, dim) >= 0) {
        storage[dim] = cloneDimStore(originalStorage[dim]);
        list._rawExtent[dim] = getInitialExtent();
        list._extent[dim] = null;
      } else {
        // Direct reference for other dimensions
        storage[dim] = originalStorage[dim];
      }
    }
  }

  return list;
}

function cloneDimStore(originalDimStore) {
  var newDimStore = new Array(originalDimStore.length);

  for (var j = 0; j < originalDimStore.length; j++) {
    newDimStore[j] = cloneChunk(originalDimStore[j]);
  }

  return newDimStore;
}

function getInitialExtent() {
  return [Infinity, -Infinity];
}
/**
 * Data mapping to a new List with given dimensions
 * @param {string|Array.<string>} dimensions
 * @param {Function} cb
 * @param {*} [context=this]
 * @return {Array}
 */


listProto.map = function (dimensions, cb, context, contextCompat) {
  'use strict'; // contextCompat just for compat echarts3

  context = context || contextCompat || this;
  dimensions = zrUtil.map(normalizeDimensions(dimensions), this.getDimension, this);
  var list = cloneListForMapAndSample(this, dimensions); // Following properties are all immutable.
  // So we can reference to the same value

  list._indices = this._indices;
  list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
  var storage = list._storage;
  var tmpRetValue = [];
  var chunkSize = this._chunkSize;
  var dimSize = dimensions.length;
  var dataCount = this.count();
  var values = [];
  var rawExtent = list._rawExtent;

  for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) {
    for (var dimIndex = 0; dimIndex < dimSize; dimIndex++) {
      values[dimIndex] = this.get(dimensions[dimIndex], dataIndex
      /*, stack */
      );
    }

    values[dimSize] = dataIndex;
    var retValue = cb && cb.apply(context, values);

    if (retValue != null) {
      // a number or string (in oridinal dimension)?
      if (typeof retValue !== 'object') {
        tmpRetValue[0] = retValue;
        retValue = tmpRetValue;
      }

      var rawIndex = this.getRawIndex(dataIndex);
      var chunkIndex = Math.floor(rawIndex / chunkSize);
      var chunkOffset = rawIndex % chunkSize;

      for (var i = 0; i < retValue.length; i++) {
        var dim = dimensions[i];
        var val = retValue[i];
        var rawExtentOnDim = rawExtent[dim];
        var dimStore = storage[dim];

        if (dimStore) {
          dimStore[chunkIndex][chunkOffset] = val;
        }

        if (val < rawExtentOnDim[0]) {
          rawExtentOnDim[0] = val;
        }

        if (val > rawExtentOnDim[1]) {
          rawExtentOnDim[1] = val;
        }
      }
    }
  }

  return list;
};
/**
 * Large data down sampling on given dimension
 * @param {string} dimension
 * @param {number} rate
 * @param {Function} sampleValue
 * @param {Function} sampleIndex Sample index for name and id
 */


listProto.downSample = function (dimension, rate, sampleValue, sampleIndex) {
  var list = cloneListForMapAndSample(this, [dimension]);
  var targetStorage = list._storage;
  var frameValues = [];
  var frameSize = Math.floor(1 / rate);
  var dimStore = targetStorage[dimension];
  var len = this.count();
  var chunkSize = this._chunkSize;
  var rawExtentOnDim = list._rawExtent[dimension];
  var newIndices = new (getIndicesCtor(this))(len);
  var offset = 0;

  for (var i = 0; i < len; i += frameSize) {
    // Last frame
    if (frameSize > len - i) {
      frameSize = len - i;
      frameValues.length = frameSize;
    }

    for (var k = 0; k < frameSize; k++) {
      var dataIdx = this.getRawIndex(i + k);
      var originalChunkIndex = Math.floor(dataIdx / chunkSize);
      var originalChunkOffset = dataIdx % chunkSize;
      frameValues[k] = dimStore[originalChunkIndex][originalChunkOffset];
    }

    var value = sampleValue(frameValues);
    var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1));
    var sampleChunkIndex = Math.floor(sampleFrameIdx / chunkSize);
    var sampleChunkOffset = sampleFrameIdx % chunkSize; // Only write value on the filtered data

    dimStore[sampleChunkIndex][sampleChunkOffset] = value;

    if (value < rawExtentOnDim[0]) {
      rawExtentOnDim[0] = value;
    }

    if (value > rawExtentOnDim[1]) {
      rawExtentOnDim[1] = value;
    }

    newIndices[offset++] = sampleFrameIdx;
  }

  list._count = offset;
  list._indices = newIndices;
  list.getRawIndex = getRawIndexWithIndices;
  return list;
};
/**
 * Get model of one data item.
 *
 * @param {number} idx
 */
// FIXME Model proxy ?


listProto.getItemModel = function (idx) {
  var hostModel = this.hostModel;
  return new Model(this.getRawDataItem(idx), hostModel, hostModel && hostModel.ecModel);
};
/**
 * Create a data differ
 * @param {module:echarts/data/List} otherList
 * @return {module:echarts/data/DataDiffer}
 */


listProto.diff = function (otherList) {
  var thisList = this;
  return new DataDiffer(otherList ? otherList.getIndices() : [], this.getIndices(), function (idx) {
    return getId(otherList, idx);
  }, function (idx) {
    return getId(thisList, idx);
  });
};
/**
 * Get visual property.
 * @param {string} key
 */


listProto.getVisual = function (key) {
  var visual = this._visual;
  return visual && visual[key];
};
/**
 * Set visual property
 * @param {string|Object} key
 * @param {*} [value]
 *
 * @example
 *  setVisual('color', color);
 *  setVisual({
 *      'color': color
 *  });
 */


listProto.setVisual = function (key, val) {
  if (isObject(key)) {
    for (var name in key) {
      if (key.hasOwnProperty(name)) {
        this.setVisual(name, key[name]);
      }
    }

    return;
  }

  this._visual = this._visual || {};
  this._visual[key] = val;
};
/**
 * Set layout property.
 * @param {string|Object} key
 * @param {*} [val]
 */


listProto.setLayout = function (key, val) {
  if (isObject(key)) {
    for (var name in key) {
      if (key.hasOwnProperty(name)) {
        this.setLayout(name, key[name]);
      }
    }

    return;
  }

  this._layout[key] = val;
};
/**
 * Get layout property.
 * @param  {string} key.
 * @return {*}
 */


listProto.getLayout = function (key) {
  return this._layout[key];
};
/**
 * Get layout of single data item
 * @param {number} idx
 */


listProto.getItemLayout = function (idx) {
  return this._itemLayouts[idx];
};
/**
 * Set layout of single data item
 * @param {number} idx
 * @param {Object} layout
 * @param {boolean=} [merge=false]
 */


listProto.setItemLayout = function (idx, layout, merge) {
  this._itemLayouts[idx] = merge ? zrUtil.extend(this._itemLayouts[idx] || {}, layout) : layout;
};
/**
 * Clear all layout of single data item
 */


listProto.clearItemLayouts = function () {
  this._itemLayouts.length = 0;
};
/**
 * Get visual property of single data item
 * @param {number} idx
 * @param {string} key
 * @param {boolean} [ignoreParent=false]
 */


listProto.getItemVisual = function (idx, key, ignoreParent) {
  var itemVisual = this._itemVisuals[idx];
  var val = itemVisual && itemVisual[key];

  if (val == null && !ignoreParent) {
    // Use global visual property
    return this.getVisual(key);
  }

  return val;
};
/**
 * Set visual property of single data item
 *
 * @param {number} idx
 * @param {string|Object} key
 * @param {*} [value]
 *
 * @example
 *  setItemVisual(0, 'color', color);
 *  setItemVisual(0, {
 *      'color': color
 *  });
 */


listProto.setItemVisual = function (idx, key, value) {
  var itemVisual = this._itemVisuals[idx] || {};
  var hasItemVisual = this.hasItemVisual;
  this._itemVisuals[idx] = itemVisual;

  if (isObject(key)) {
    for (var name in key) {
      if (key.hasOwnProperty(name)) {
        itemVisual[name] = key[name];
        hasItemVisual[name] = true;
      }
    }

    return;
  }

  itemVisual[key] = value;
  hasItemVisual[key] = true;
};
/**
 * Clear itemVisuals and list visual.
 */


listProto.clearAllVisual = function () {
  this._visual = {};
  this._itemVisuals = [];
  this.hasItemVisual = {};
};

var setItemDataAndSeriesIndex = function (child) {
  child.seriesIndex = this.seriesIndex;
  child.dataIndex = this.dataIndex;
  child.dataType = this.dataType;
};
/**
 * Set graphic element relative to data. It can be set as null
 * @param {number} idx
 * @param {module:zrender/Element} [el]
 */


listProto.setItemGraphicEl = function (idx, el) {
  var hostModel = this.hostModel;

  if (el) {
    // Add data index and series index for indexing the data by element
    // Useful in tooltip
    el.dataIndex = idx;
    el.dataType = this.dataType;
    el.seriesIndex = hostModel && hostModel.seriesIndex;

    if (el.type === 'group') {
      el.traverse(setItemDataAndSeriesIndex, el);
    }
  }

  this._graphicEls[idx] = el;
};
/**
 * @param {number} idx
 * @return {module:zrender/Element}
 */


listProto.getItemGraphicEl = function (idx) {
  return this._graphicEls[idx];
};
/**
 * @param {Function} cb
 * @param {*} context
 */


listProto.eachItemGraphicEl = function (cb, context) {
  zrUtil.each(this._graphicEls, function (el, idx) {
    if (el) {
      cb && cb.call(context, el, idx);
    }
  });
};
/**
 * Shallow clone a new list except visual and layout properties, and graph elements.
 * New list only change the indices.
 */


listProto.cloneShallow = function (list) {
  if (!list) {
    var dimensionInfoList = zrUtil.map(this.dimensions, this.getDimensionInfo, this);
    list = new List(dimensionInfoList, this.hostModel);
  } // FIXME


  list._storage = this._storage;
  transferProperties(list, this); // Clone will not change the data extent and indices

  if (this._indices) {
    var Ctor = this._indices.constructor;
    list._indices = new Ctor(this._indices);
  } else {
    list._indices = null;
  }

  list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices;
  return list;
};
/**
 * Wrap some method to add more feature
 * @param {string} methodName
 * @param {Function} injectFunction
 */


listProto.wrapMethod = function (methodName, injectFunction) {
  var originalMethod = this[methodName];

  if (typeof originalMethod !== 'function') {
    return;
  }

  this.__wrappedMethods = this.__wrappedMethods || [];

  this.__wrappedMethods.push(methodName);

  this[methodName] = function () {
    var res = originalMethod.apply(this, arguments);
    return injectFunction.apply(this, [res].concat(zrUtil.slice(arguments)));
  };
}; // Methods that create a new list based on this list should be listed here.
// Notice that those method should `RETURN` the new list.


listProto.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'map']; // Methods that change indices of this list should be listed here.

listProto.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
export default List;