import Geo3D from './geo3D/Geo3D';
import * as echarts from 'echarts/lib/echarts';
import { getLayoutRect } from 'echarts/lib/util/layout';
import ViewGL from '../core/ViewGL';
import retrieve from '../util/retrieve';

function resizeGeo3D(geo3DModel, api) {
  // Use left/top/width/height
  var boxLayoutOption = geo3DModel.getBoxLayoutParams();
  var viewport = getLayoutRect(boxLayoutOption, {
    width: api.getWidth(),
    height: api.getHeight()
  }); // Flip Y

  viewport.y = api.getHeight() - viewport.y - viewport.height;
  this.viewGL.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, api.getDevicePixelRatio());
  var geoRect = this.getGeoBoundingRect();
  var aspect = geoRect.width / geoRect.height * (geo3DModel.get('aspectScale') || 0.75);
  var width = geo3DModel.get('boxWidth');
  var depth = geo3DModel.get('boxDepth');
  var height = geo3DModel.get('boxHeight');

  if (height == null) {
    height = 5;
  }

  if (isNaN(width) && isNaN(depth)) {
    // Default to have 100 width
    width = 100;
  }

  if (isNaN(depth)) {
    depth = width / aspect;
  } else if (isNaN(width)) {
    width = depth / aspect;
  }

  this.setSize(width, height, depth);
  this.regionHeight = geo3DModel.get('regionHeight');

  if (this.altitudeAxis) {
    this.altitudeAxis.setExtent(0, Math.max(height - this.regionHeight, 0));
  }
}

function updateGeo3D(ecModel, api) {
  var altitudeDataExtent = [Infinity, -Infinity];
  ecModel.eachSeries(function (seriesModel) {
    if (seriesModel.coordinateSystem !== this) {
      return;
    }

    if (seriesModel.type === 'series.map3D') {
      return;
    } // Get altitude data extent.


    var data = seriesModel.getData();
    var altDims = seriesModel.coordDimToDataDim('alt');
    var altDim = altDims && altDims[0];

    if (altDim) {
      // TODO altitiude is in coords of lines.
      var dataExtent = data.getDataExtent(altDim, true);
      altitudeDataExtent[0] = Math.min(altitudeDataExtent[0], dataExtent[0]);
      altitudeDataExtent[1] = Math.max(altitudeDataExtent[1], dataExtent[1]);
    }
  }, this); // Create altitude axis

  if (altitudeDataExtent && isFinite(altitudeDataExtent[1] - altitudeDataExtent[0])) {
    var scale = echarts.helper.createScale(altitudeDataExtent, {
      type: 'value',
      // PENDING
      min: 'dataMin',
      max: 'dataMax'
    });
    this.altitudeAxis = new echarts.Axis('altitude', scale); // Resize again

    this.resize(this.model, api);
  }
}

if (process.env.NODE_ENV !== 'production') {
  var mapNotExistsError = function (name) {
    console.error('Map ' + name + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html');
  };
}

var idStart = 0;
var geo3DCreator = {
  dimensions: Geo3D.prototype.dimensions,
  create: function (ecModel, api) {
    var geo3DList = [];

    if (!echarts.getMap) {
      throw new Error('geo3D component depends on geo component');
    }

    function createGeo3D(componentModel, idx) {
      var geo3D = geo3DCreator.createGeo3D(componentModel); // FIXME

      componentModel.__viewGL = componentModel.__viewGL || new ViewGL();
      geo3D.viewGL = componentModel.__viewGL;
      componentModel.coordinateSystem = geo3D;
      geo3D.model = componentModel;
      geo3DList.push(geo3D); // Inject resize

      geo3D.resize = resizeGeo3D;
      geo3D.resize(componentModel, api);
      geo3D.update = updateGeo3D;
    }

    ecModel.eachComponent('geo3D', function (geo3DModel, idx) {
      createGeo3D(geo3DModel, idx);
    });
    ecModel.eachSeriesByType('map3D', function (map3DModel, idx) {
      var coordSys = map3DModel.get('coordinateSystem');

      if (coordSys == null) {
        coordSys = 'geo3D';
      }

      if (coordSys === 'geo3D') {
        createGeo3D(map3DModel, idx);
      }
    });
    ecModel.eachSeries(function (seriesModel) {
      if (seriesModel.get('coordinateSystem') === 'geo3D') {
        if (seriesModel.type === 'series.map3D') {
          return;
        }

        var geo3DModel = seriesModel.getReferringComponents('geo3D').models[0];

        if (!geo3DModel) {
          geo3DModel = ecModel.getComponent('geo3D');
        }

        if (!geo3DModel) {
          throw new Error('geo "' + retrieve.firstNotNull(seriesModel.get('geo3DIndex'), seriesModel.get('geo3DId'), 0) + '" not found');
        }

        seriesModel.coordinateSystem = geo3DModel.coordinateSystem;
      }
    });
    return geo3DList;
  },
  createGeo3D: function (componentModel) {
    var mapData = componentModel.get('map');
    var name;

    if (typeof mapData === 'string') {
      name = mapData;
      mapData = echarts.getMap(mapData);
    } else {
      if (mapData && mapData.features) {
        mapData = {
          geoJson: mapData
        };
      }
    }

    if (process.env.NODE_ENV !== 'production') {
      if (!mapData) {
        mapNotExistsError(mapData);
      }

      if (!mapData.geoJson.features) {
        throw new Error('Invalid GeoJSON for map3D');
      }
    }

    if (name == null) {
      name = 'GEO_ANONYMOUS_' + idStart++;
    }

    return new Geo3D(name + idStart++, name, mapData && mapData.geoJson, mapData && mapData.specialAreas, componentModel.get('nameMap'));
  }
};
export default geo3DCreator;