/*
* 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.
*/
// Only create one roam controller for each coordinate system.
// one roam controller might be refered by two inside data zoom
// components (for example, one for x and one for y). When user
// pan or zoom, only dispatch one action for those data zoom
// components.
import * as zrUtil from 'zrender/src/core/util';
import RoamController from '../../component/helper/RoamController';
import * as throttleUtil from '../../util/throttle';
var ATTR = '\0_ec_dataZoom_roams';
/**
 * @public
 * @param {module:echarts/ExtensionAPI} api
 * @param {Object} dataZoomInfo
 * @param {string} dataZoomInfo.coordId
 * @param {Function} dataZoomInfo.containsPoint
 * @param {Array.<string>} dataZoomInfo.allCoordIds
 * @param {string} dataZoomInfo.dataZoomId
 * @param {Object} dataZoomInfo.getRange
 * @param {Function} dataZoomInfo.getRange.pan
 * @param {Function} dataZoomInfo.getRange.zoom
 * @param {Function} dataZoomInfo.getRange.scrollMove
 * @param {boolean} dataZoomInfo.dataZoomModel
 */

export function register(api, dataZoomInfo) {
  var store = giveStore(api);
  var theDataZoomId = dataZoomInfo.dataZoomId;
  var theCoordId = dataZoomInfo.coordId; // Do clean when a dataZoom changes its target coordnate system.
  // Avoid memory leak, dispose all not-used-registered.

  zrUtil.each(store, function (record, coordId) {
    var dataZoomInfos = record.dataZoomInfos;

    if (dataZoomInfos[theDataZoomId] && zrUtil.indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0) {
      delete dataZoomInfos[theDataZoomId];
      record.count--;
    }
  });
  cleanStore(store);
  var record = store[theCoordId]; // Create if needed.

  if (!record) {
    record = store[theCoordId] = {
      coordId: theCoordId,
      dataZoomInfos: {},
      count: 0
    };
    record.controller = createController(api, record);
    record.dispatchAction = zrUtil.curry(dispatchAction, api);
  } // Update reference of dataZoom.


  !record.dataZoomInfos[theDataZoomId] && record.count++;
  record.dataZoomInfos[theDataZoomId] = dataZoomInfo;
  var controllerParams = mergeControllerParams(record.dataZoomInfos);
  record.controller.enable(controllerParams.controlType, controllerParams.opt); // Consider resize, area should be always updated.

  record.controller.setPointerChecker(dataZoomInfo.containsPoint); // Update throttle.

  throttleUtil.createOrUpdate(record, 'dispatchAction', dataZoomInfo.dataZoomModel.get('throttle', true), 'fixRate');
}
/**
 * @public
 * @param {module:echarts/ExtensionAPI} api
 * @param {string} dataZoomId
 */

export function unregister(api, dataZoomId) {
  var store = giveStore(api);
  zrUtil.each(store, function (record) {
    record.controller.dispose();
    var dataZoomInfos = record.dataZoomInfos;

    if (dataZoomInfos[dataZoomId]) {
      delete dataZoomInfos[dataZoomId];
      record.count--;
    }
  });
  cleanStore(store);
}
/**
 * @public
 */

export function generateCoordId(coordModel) {
  return coordModel.type + '\0_' + coordModel.id;
}
/**
 * Key: coordId, value: {dataZoomInfos: [], count, controller}
 * @type {Array.<Object>}
 */

function giveStore(api) {
  // Mount store on zrender instance, so that we do not
  // need to worry about dispose.
  var zr = api.getZr();
  return zr[ATTR] || (zr[ATTR] = {});
}

function createController(api, newRecord) {
  var controller = new RoamController(api.getZr());
  zrUtil.each(['pan', 'zoom', 'scrollMove'], function (eventName) {
    controller.on(eventName, function (event) {
      var batch = [];
      zrUtil.each(newRecord.dataZoomInfos, function (info) {
        // Check whether the behaviors (zoomOnMouseWheel, moveOnMouseMove,
        // moveOnMouseWheel, ...) enabled.
        if (!event.isAvailableBehavior(info.dataZoomModel.option)) {
          return;
        }

        var method = (info.getRange || {})[eventName];
        var range = method && method(newRecord.controller, event);
        !info.dataZoomModel.get('disabled', true) && range && batch.push({
          dataZoomId: info.dataZoomId,
          start: range[0],
          end: range[1]
        });
      });
      batch.length && newRecord.dispatchAction(batch);
    });
  });
  return controller;
}

function cleanStore(store) {
  zrUtil.each(store, function (record, coordId) {
    if (!record.count) {
      record.controller.dispose();
      delete store[coordId];
    }
  });
}
/**
 * This action will be throttled.
 */


function dispatchAction(api, batch) {
  api.dispatchAction({
    type: 'dataZoom',
    batch: batch
  });
}
/**
 * Merge roamController settings when multiple dataZooms share one roamController.
 */


function mergeControllerParams(dataZoomInfos) {
  var controlType; // DO NOT use reserved word (true, false, undefined) as key literally. Even if encapsulated
  // as string, it is probably revert to reserved word by compress tool. See #7411.

  var prefix = 'type_';
  var typePriority = {
    'type_true': 2,
    'type_move': 1,
    'type_false': 0,
    'type_undefined': -1
  };
  var preventDefaultMouseMove = true;
  zrUtil.each(dataZoomInfos, function (dataZoomInfo) {
    var dataZoomModel = dataZoomInfo.dataZoomModel;
    var oneType = dataZoomModel.get('disabled', true) ? false : dataZoomModel.get('zoomLock', true) ? 'move' : true;

    if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) {
      controlType = oneType;
    } // Prevent default move event by default. If one false, do not prevent. Otherwise
    // users may be confused why it does not work when multiple insideZooms exist.


    preventDefaultMouseMove &= dataZoomModel.get('preventDefaultMouseMove', true);
  });
  return {
    controlType: controlType,
    opt: {
      // RoamController will enable all of these functionalities,
      // and the final behavior is determined by its event listener
      // provided by each inside zoom.
      zoomOnMouseWheel: true,
      moveOnMouseMove: true,
      moveOnMouseWheel: true,
      preventDefaultMouseMove: !!preventDefaultMouseMove
    }
  };
}