/*
* 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.
*/
// TODO
// ??? refactor? check the outer usage of data provider.
// merge with defaultDimValueGetter?
import { __DEV__ } from '../../config';
import { isTypedArray, extend, assert, each, isObject } from 'zrender/src/core/util';
import { getDataItemValue, isDataItemOption } from '../../util/model';
import { parseDate } from '../../util/number';
import Source from '../Source';
import { SOURCE_FORMAT_TYPED_ARRAY, SOURCE_FORMAT_ARRAY_ROWS, SOURCE_FORMAT_ORIGINAL, SOURCE_FORMAT_OBJECT_ROWS } from './sourceType';
/**
 * If normal array used, mutable chunk size is supported.
 * If typed array used, chunk size must be fixed.
 */

export function DefaultDataProvider(source, dimSize) {
  if (!Source.isInstance(source)) {
    source = Source.seriesDataToSource(source);
  }

  this._source = source;
  var data = this._data = source.data;
  var sourceFormat = source.sourceFormat; // Typed array. TODO IE10+?

  if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) {
    this._offset = 0;
    this._dimSize = dimSize;
    this._data = data;
  }

  var methods = providerMethods[sourceFormat === SOURCE_FORMAT_ARRAY_ROWS ? sourceFormat + '_' + source.seriesLayoutBy : sourceFormat];
  extend(this, methods);
}
var providerProto = DefaultDataProvider.prototype; // If data is pure without style configuration

providerProto.pure = false; // If data is persistent and will not be released after use.

providerProto.persistent = true; // ???! FIXME legacy data provider do not has method getSource

providerProto.getSource = function () {
  return this._source;
};

var providerMethods = {
  'arrayRows_column': {
    pure: true,
    count: function () {
      return Math.max(0, this._data.length - this._source.startIndex);
    },
    getItem: function (idx) {
      return this._data[idx + this._source.startIndex];
    },
    appendData: appendDataSimply
  },
  'arrayRows_row': {
    pure: true,
    count: function () {
      var row = this._data[0];
      return row ? Math.max(0, row.length - this._source.startIndex) : 0;
    },
    getItem: function (idx) {
      idx += this._source.startIndex;
      var item = [];
      var data = this._data;

      for (var i = 0; i < data.length; i++) {
        var row = data[i];
        item.push(row ? row[idx] : null);
      }

      return item;
    },
    appendData: function () {
      throw new Error('Do not support appendData when set seriesLayoutBy: "row".');
    }
  },
  'objectRows': {
    pure: true,
    count: countSimply,
    getItem: getItemSimply,
    appendData: appendDataSimply
  },
  'keyedColumns': {
    pure: true,
    count: function () {
      var dimName = this._source.dimensionsDefine[0].name;
      var col = this._data[dimName];
      return col ? col.length : 0;
    },
    getItem: function (idx) {
      var item = [];
      var dims = this._source.dimensionsDefine;

      for (var i = 0; i < dims.length; i++) {
        var col = this._data[dims[i].name];
        item.push(col ? col[idx] : null);
      }

      return item;
    },
    appendData: function (newData) {
      var data = this._data;
      each(newData, function (newCol, key) {
        var oldCol = data[key] || (data[key] = []);

        for (var i = 0; i < (newCol || []).length; i++) {
          oldCol.push(newCol[i]);
        }
      });
    }
  },
  'original': {
    count: countSimply,
    getItem: getItemSimply,
    appendData: appendDataSimply
  },
  'typedArray': {
    persistent: false,
    pure: true,
    count: function () {
      return this._data ? this._data.length / this._dimSize : 0;
    },
    getItem: function (idx, out) {
      idx = idx - this._offset;
      out = out || [];
      var offset = this._dimSize * idx;

      for (var i = 0; i < this._dimSize; i++) {
        out[i] = this._data[offset + i];
      }

      return out;
    },
    appendData: function (newData) {
      this._data = newData;
    },
    // Clean self if data is already used.
    clean: function () {
      // PENDING
      this._offset += this.count();
      this._data = null;
    }
  }
};

function countSimply() {
  return this._data.length;
}

function getItemSimply(idx) {
  return this._data[idx];
}

function appendDataSimply(newData) {
  for (var i = 0; i < newData.length; i++) {
    this._data.push(newData[i]);
  }
}

var rawValueGetters = {
  arrayRows: getRawValueSimply,
  objectRows: function (dataItem, dataIndex, dimIndex, dimName) {
    return dimIndex != null ? dataItem[dimName] : dataItem;
  },
  keyedColumns: getRawValueSimply,
  original: function (dataItem, dataIndex, dimIndex, dimName) {
    // FIXME
    // In some case (markpoint in geo (geo-map.html)), dataItem
    // is {coord: [...]}
    var value = getDataItemValue(dataItem);
    return dimIndex == null || !(value instanceof Array) ? value : value[dimIndex];
  },
  typedArray: getRawValueSimply
};

function getRawValueSimply(dataItem, dataIndex, dimIndex, dimName) {
  return dimIndex != null ? dataItem[dimIndex] : dataItem;
}

export var defaultDimValueGetters = {
  arrayRows: getDimValueSimply,
  objectRows: function (dataItem, dimName, dataIndex, dimIndex) {
    return converDataValue(dataItem[dimName], this._dimensionInfos[dimName]);
  },
  keyedColumns: getDimValueSimply,
  original: function (dataItem, dimName, dataIndex, dimIndex) {
    // Performance sensitive, do not use modelUtil.getDataItemValue.
    // If dataItem is an plain object with no value field, the var `value`
    // will be assigned with the object, but it will be tread correctly
    // in the `convertDataValue`.
    var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value); // If any dataItem is like { value: 10 }

    if (!this._rawData.pure && isDataItemOption(dataItem)) {
      this.hasItemOption = true;
    }

    return converDataValue(value instanceof Array ? value[dimIndex] // If value is a single number or something else not array.
    : value, this._dimensionInfos[dimName]);
  },
  typedArray: function (dataItem, dimName, dataIndex, dimIndex) {
    return dataItem[dimIndex];
  }
};

function getDimValueSimply(dataItem, dimName, dataIndex, dimIndex) {
  return converDataValue(dataItem[dimIndex], this._dimensionInfos[dimName]);
}
/**
 * This helper method convert value in data.
 * @param {string|number|Date} value
 * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'.
 *        If "dimInfo.ordinalParseAndSave", ordinal value can be parsed.
 */


function converDataValue(value, dimInfo) {
  // Performance sensitive.
  var dimType = dimInfo && dimInfo.type;

  if (dimType === 'ordinal') {
    // If given value is a category string
    var ordinalMeta = dimInfo && dimInfo.ordinalMeta;
    return ordinalMeta ? ordinalMeta.parseAndCollect(value) : value;
  }

  if (dimType === 'time' // spead up when using timestamp
  && typeof value !== 'number' && value != null && value !== '-') {
    value = +parseDate(value);
  } // dimType defaults 'number'.
  // If dimType is not ordinal and value is null or undefined or NaN or '-',
  // parse to NaN.


  return value == null || value === '' ? NaN // If string (like '-'), using '+' parse to NaN
  // If object, also parse to NaN
  : +value;
} // ??? FIXME can these logic be more neat: getRawValue, getRawDataItem,
// Consider persistent.
// Caution: why use raw value to display on label or tooltip?
// A reason is to avoid format. For example time value we do not know
// how to format is expected. More over, if stack is used, calculated
// value may be 0.91000000001, which have brings trouble to display.
// TODO: consider how to treat null/undefined/NaN when display?

/**
 * @param {module:echarts/data/List} data
 * @param {number} dataIndex
 * @param {string|number} [dim] dimName or dimIndex
 * @return {Array.<number>|string|number} can be null/undefined.
 */


export function retrieveRawValue(data, dataIndex, dim) {
  if (!data) {
    return;
  } // Consider data may be not persistent.


  var dataItem = data.getRawDataItem(dataIndex);

  if (dataItem == null) {
    return;
  }

  var sourceFormat = data.getProvider().getSource().sourceFormat;
  var dimName;
  var dimIndex;
  var dimInfo = data.getDimensionInfo(dim);

  if (dimInfo) {
    dimName = dimInfo.name;
    dimIndex = dimInfo.index;
  }

  return rawValueGetters[sourceFormat](dataItem, dataIndex, dimIndex, dimName);
}
/**
 * Compatible with some cases (in pie, map) like:
 * data: [{name: 'xx', value: 5, selected: true}, ...]
 * where only sourceFormat is 'original' and 'objectRows' supported.
 *
 * ??? TODO
 * Supported detail options in data item when using 'arrayRows'.
 *
 * @param {module:echarts/data/List} data
 * @param {number} dataIndex
 * @param {string} attr like 'selected'
 */

export function retrieveRawAttr(data, dataIndex, attr) {
  if (!data) {
    return;
  }

  var sourceFormat = data.getProvider().getSource().sourceFormat;

  if (sourceFormat !== SOURCE_FORMAT_ORIGINAL && sourceFormat !== SOURCE_FORMAT_OBJECT_ROWS) {
    return;
  }

  var dataItem = data.getRawDataItem(dataIndex);

  if (sourceFormat === SOURCE_FORMAT_ORIGINAL && !isObject(dataItem)) {
    dataItem = null;
  }

  if (dataItem) {
    return dataItem[attr];
  }
}