// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT

import { packageName } from '../config';

/**
 * Translate the token's sight distance in units into a radius in pixels.
 * @return {number} The sight radius in pixels
 */
export function getDimRadius() {
  const dimSight = getDimVision.call(this);
  let r = Math.abs(this.data.dimLight) > Math.abs(dimSight) ? this.data.dimLight : dimSight;
  return this.getLightRadius(r);
}

/**
 * Translate the token's bright light distance in units into a radius in pixels.
 * @return {number} The bright radius in pixels
 */
export function getBrightRadius() {
  const brightSight = getBrightVision.call(this);
  let r = Math.abs(this.data.brightLight) > Math.abs(brightSight) ? this.data.brightLight : brightSight;
  return this.getLightRadius(r);
}

/**
 * Update an Token vision source associated for this token.
 * @param {boolean} [defer]           Defer refreshing the LightingLayer to manually call that refresh later.
 * @param {boolean} [deleted]         Indicate that this vision source has been deleted.
 * @param {boolean} [skipUpdateFog]   Never update the Fog exploration progress for this update.
 */
export function updateVisionSource({ defer = false, deleted = false, skipUpdateFog = false } = {}) {
  // Prepare data
  const origin = this.getSightOrigin();
  const sourceId = this.sourceId;
  const d = canvas.dimensions;
  const isVisionSource = this._isVisionSource();

  // Initialize vision source
  if (isVisionSource && !deleted) {
    const dimSight = getDimVision.call(this);
    const brightSight = getBrightVision.call(this);
    let dim = Math.min(this.getLightRadius(dimSight), d.maxR);
    const bright = Math.min(this.getLightRadius(brightSight), d.maxR);
    this.vision.initialize({
      x: origin.x,
      y: origin.y,
      dim: dim,
      bright: bright,
      angle: this.data.sightAngle,
      rotation: this.data.rotation,
    });
    canvas.sight.sources.set(sourceId, this.vision);
  }

  // Remove vision source
  else canvas.sight.sources.delete(sourceId);

  // Schedule a perception update
  if (!defer && (isVisionSource || deleted))
    canvas.perception.schedule({
      sight: { refresh: true, skipUpdateFog },
    });
}

/**
 * Does this {@link Token} have dim vision, considering the darkness level of
 * its containing {@link Scene}?
 */
function hasDimVision() {
  const dimVisionDarknessMin = this.document.getFlag(packageName, 'dimVisionDarknessMin') ?? 0;
  const dimVisionDarknessMax = this.document.getFlag(packageName, 'dimVisionDarknessMax') ?? 1;
  const darkness = this.document.parent.data.darkness;
  return dimVisionDarknessMin <= darkness && darkness <= dimVisionDarknessMax;
}

/**
 * Does this {@link Token} have bright vision, considering the darkness level of
 * its containing {@link Scene}?
 */
function hasBrightVision() {
  const brightVisionDarknessMin = this.document.getFlag(packageName, 'brightVisionDarknessMin') ?? 0;
  const brightVisionDarknessMax = this.document.getFlag(packageName, 'brightVisionDarknessMax') ?? 1;
  const darkness = this.document.parent.data.darkness;
  return brightVisionDarknessMin <= darkness && darkness <= brightVisionDarknessMax;
}

/**
 * Get this {@link Token}'s dim vision distance of in grid units, considering
 * the darkness level of its containing {@link Scene}.
 *
 * @returns {number} The the number of grid units that this {@link Token} has
 * dim vision
 */
function getDimVision() {
  return hasDimVision.call(this) ? this.data.dimSight : 0;
}

/**
 * Get this {@link Token}'s bright vision distance in grid units, considering
 * the darkness level of its containing {@link Scene}.
 *
 * @returns {number} The the number of grid units that this {@link Token} has
 * bright vision
 */
function getBrightVision() {
  return hasBrightVision.call(this) ? this.data.brightSight : 0;
}