/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::collections::HashMap;

use embedder_traits::{TouchId, TouchSequenceId};
use euclid::{Point2D, Scale, Vector2D};
use log::{debug, error, warn};
use webrender_api::units::{DeviceIntPoint, DevicePixel, DevicePoint, LayoutVector2D};

use self::TouchSequenceState::*;

// TODO: All `_SCREEN_PX` units below are currently actually used as `DevicePixel`
// without multiplying with the `hidpi_factor`. This should be fixed and the
// constants adjusted accordingly.
/// Minimum number of `DeviceIndependentPixel` to begin touch scrolling.
const TOUCH_PAN_MIN_SCREEN_PX: f32 = 20.0;
/// Factor by which the flinging velocity changes on each tick.
const FLING_SCALING_FACTOR: f32 = 0.95;
/// Minimum velocity required for transitioning to fling when panning ends.
const FLING_MIN_SCREEN_PX: f32 = 3.0;
/// Maximum velocity when flinging.
const FLING_MAX_SCREEN_PX: f32 = 4000.0;

pub struct TouchHandler {
    pub current_sequence_id: TouchSequenceId,
    // todo: VecDeque + modulo arithmetic would be more efficient.
    touch_sequence_map: HashMap<TouchSequenceId, TouchSequenceInfo>,
}

/// Whether the default move action is allowed or not.
#[derive(Debug, Eq, PartialEq)]
pub enum TouchMoveAllowed {
    /// The default move action is prevented by script
    Prevented,
    /// The default move action is allowed
    Allowed,
    /// The initial move handler result is still pending
    Pending,
}

pub struct TouchSequenceInfo {
    /// touch sequence state
    pub(crate) state: TouchSequenceState,
    /// touch sequence active touch points
    active_touch_points: Vec<TouchPoint>,
    /// The script thread is already processing a touchmove operation.
    ///
    /// We use this to skip sending the event to the script thread,
    /// to prevent overloading script.
    handling_touch_move: bool,
    /// Do not perform a click action.
    ///
    /// This happens when
    /// - We had a touch move larger than the minimum distance OR
    /// - We had multiple active touchpoints OR
    /// - `preventDefault()` was called in a touch_down or touch_up handler
    pub prevent_click: bool,
    /// Whether move is allowed, prevented or the result is still pending.
    /// Once the first move has been processed by script, we can transition to
    /// non-cancellable events, and directly perform the pan without waiting for script.
    pub prevent_move: TouchMoveAllowed,
    /// Move operation waiting to be processed in the touch sequence.
    ///
    /// This is only used while the first touch move is processed in script.
    /// Todo: It would be nice to merge this into the TouchSequenceState, but
    /// this requires some additional work to handle the merging of pending
    /// touch move events. Presumably if we keep a history of previous touch points,
    /// this would allow a better fling algorithm and easier merging of zoom events.
    pending_touch_move_action: Option<TouchMoveAction>,
}

impl TouchSequenceInfo {
    fn touch_count(&self) -> usize {
        self.active_touch_points.len()
    }

    fn pinch_distance_and_center(&self) -> (f32, Point2D<f32, DevicePixel>) {
        debug_assert_eq!(self.touch_count(), 2);
        let p0 = self.active_touch_points[0].point;
        let p1 = self.active_touch_points[1].point;
        let center = p0.lerp(p1, 0.5);
        let distance = (p0 - p1).length();

        (distance, center)
    }

    fn update_pending_touch_move_action(&mut self, action: TouchMoveAction) {
        debug_assert!(self.prevent_move == TouchMoveAllowed::Pending);

        if let Some(pre_action) = self.pending_touch_move_action {
            let combine_action = match (pre_action, action) {
                (TouchMoveAction::NoAction, _) | (_, TouchMoveAction::NoAction) => action,
                // Combine touch move action.
                (TouchMoveAction::Scroll(delta, point), TouchMoveAction::Scroll(delta_new, _)) => {
                    TouchMoveAction::Scroll(delta + delta_new, point)
                },
                (
                    TouchMoveAction::Scroll(delta, _),
                    TouchMoveAction::Zoom(magnification, scroll_delta),
                ) |
                (
                    TouchMoveAction::Zoom(magnification, scroll_delta),
                    TouchMoveAction::Scroll(delta, _),
                ) => {
                    // Todo: It's unclear what the best action would be. Should we keep both
                    // scroll and zoom?
                    TouchMoveAction::Zoom(magnification, delta + scroll_delta)
                },
                (
                    TouchMoveAction::Zoom(magnification, scroll_delta),
                    TouchMoveAction::Zoom(magnification_new, scroll_delta_new),
                ) => TouchMoveAction::Zoom(
                    magnification * magnification_new,
                    scroll_delta + scroll_delta_new,
                ),
            };
            self.pending_touch_move_action = Some(combine_action);
        } else {
            self.pending_touch_move_action = Some(action);
        }
    }

    /// Returns true when all touch events of a sequence have been received.
    /// This does not mean that all event handlers have finished yet.
    fn is_finished(&self) -> bool {
        matches!(
            self.state,
            Finished | Flinging { .. } | PendingFling { .. } | PendingClick(_)
        )
    }
}

/// An action that can be immediately performed in response to a touch move event
/// without waiting for script.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TouchMoveAction {
    /// Scroll by the provided offset.
    Scroll(Vector2D<f32, DevicePixel>, DevicePoint),
    /// Zoom by a magnification factor and scroll by the provided offset.
    Zoom(f32, Vector2D<f32, DevicePixel>),
    /// Don't do anything.
    NoAction,
}

#[derive(Clone, Copy, Debug)]
pub struct TouchPoint {
    pub id: TouchId,
    pub point: Point2D<f32, DevicePixel>,
}

impl TouchPoint {
    pub fn new(id: TouchId, point: Point2D<f32, DevicePixel>) -> Self {
        TouchPoint { id, point }
    }
}

/// The states of the touch input state machine.
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) enum TouchSequenceState {
    /// touch point is active but does not start moving
    Touching,
    /// A single touch point is active and has started panning.
    Panning {
        velocity: Vector2D<f32, DevicePixel>,
    },
    /// A two-finger pinch zoom gesture is active.
    Pinching,
    /// A multi-touch gesture is in progress.
    MultiTouch,
    // All states below here are reached after a touch-up, i.e. all events of the sequence
    // have already been received.
    /// The initial touch move handler has not finished processing yet, so we need to wait
    /// for the result in order to transition to fling.
    PendingFling {
        velocity: Vector2D<f32, DevicePixel>,
        cursor: DeviceIntPoint,
    },
    /// No active touch points, but there is still scrolling velocity
    Flinging {
        velocity: Vector2D<f32, DevicePixel>,
        cursor: DeviceIntPoint,
    },
    /// The touch sequence is finished, but a click is still pending, waiting on script.
    PendingClick(DevicePoint),
    /// touch sequence finished.
    Finished,
}

pub(crate) struct FlingAction {
    pub delta: LayoutVector2D,
    pub cursor: DeviceIntPoint,
}

impl TouchHandler {
    pub fn new() -> Self {
        let finished_info = TouchSequenceInfo {
            state: TouchSequenceState::Finished,
            active_touch_points: vec![],
            handling_touch_move: false,
            prevent_click: false,
            prevent_move: TouchMoveAllowed::Pending,
            pending_touch_move_action: None,
        };
        TouchHandler {
            current_sequence_id: TouchSequenceId::new(),
            // We insert a simulated initial touch sequence, which is already finished,
            // so that we always have one element in the map, which simplifies creating
            // a new touch sequence on touch_down.
            touch_sequence_map: HashMap::from([(TouchSequenceId::new(), finished_info)]),
        }
    }

    pub(crate) fn set_handling_touch_move(&mut self, sequence_id: TouchSequenceId, flag: bool) {
        if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
            sequence.handling_touch_move = flag;
        }
    }

    pub(crate) fn is_handling_touch_move(&self, sequence_id: TouchSequenceId) -> bool {
        if let Some(sequence) = self.touch_sequence_map.get(&sequence_id) {
            sequence.handling_touch_move
        } else {
            false
        }
    }

    pub(crate) fn prevent_click(&mut self, sequence_id: TouchSequenceId) {
        if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
            sequence.prevent_click = true;
        } else {
            warn!("TouchSequenceInfo corresponding to the sequence number has been deleted.");
        }
    }

    pub(crate) fn prevent_move(&mut self, sequence_id: TouchSequenceId) {
        if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
            sequence.prevent_move = TouchMoveAllowed::Prevented;
        } else {
            warn!("TouchSequenceInfo corresponding to the sequence number has been deleted.");
        }
    }

    /// Returns true if default move actions are allowed, false if prevented or the result
    /// is still pending.,
    pub(crate) fn move_allowed(&mut self, sequence_id: TouchSequenceId) -> bool {
        if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
            sequence.prevent_move == TouchMoveAllowed::Allowed
        } else {
            true
        }
    }

    pub(crate) fn pending_touch_move_action(
        &mut self,
        sequence_id: TouchSequenceId,
    ) -> Option<TouchMoveAction> {
        match self.touch_sequence_map.get(&sequence_id) {
            Some(sequence) => sequence.pending_touch_move_action,
            None => None,
        }
    }

    pub(crate) fn remove_pending_touch_move_action(&mut self, sequence_id: TouchSequenceId) {
        if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
            sequence.pending_touch_move_action = None;
        }
    }

    // try to remove touch sequence, if touch sequence end and not has pending action.
    pub(crate) fn try_remove_touch_sequence(&mut self, sequence_id: TouchSequenceId) {
        if let Some(sequence) = self.touch_sequence_map.get(&sequence_id) {
            if sequence.pending_touch_move_action.is_none() && sequence.state == Finished {
                self.touch_sequence_map.remove(&sequence_id);
            }
        }
    }

    pub(crate) fn remove_touch_sequence(&mut self, sequence_id: TouchSequenceId) {
        let old = self.touch_sequence_map.remove(&sequence_id);
        debug_assert!(old.is_some(), "Sequence already removed?");
    }

    pub fn try_get_current_touch_sequence(&self) -> Option<&TouchSequenceInfo> {
        self.touch_sequence_map.get(&self.current_sequence_id)
    }

    pub fn get_current_touch_sequence_mut(&mut self) -> &mut TouchSequenceInfo {
        self.touch_sequence_map
            .get_mut(&self.current_sequence_id)
            .expect("Current Touch sequence does not exist")
    }

    fn try_get_current_touch_sequence_mut(&mut self) -> Option<&mut TouchSequenceInfo> {
        self.touch_sequence_map.get_mut(&self.current_sequence_id)
    }

    pub(crate) fn get_touch_sequence(&self, sequence_id: TouchSequenceId) -> &TouchSequenceInfo {
        self.touch_sequence_map
            .get(&sequence_id)
            .expect("Touch sequence not found.")
    }
    pub(crate) fn get_touch_sequence_mut(
        &mut self,
        sequence_id: TouchSequenceId,
    ) -> Option<&mut TouchSequenceInfo> {
        self.touch_sequence_map.get_mut(&sequence_id)
    }

    pub fn on_touch_down(&mut self, id: TouchId, point: Point2D<f32, DevicePixel>) {
        // if the current sequence ID does not exist in the map, then it was already handled
        if !self
            .touch_sequence_map
            .contains_key(&self.current_sequence_id) ||
            self.get_touch_sequence(self.current_sequence_id)
                .is_finished()
        {
            self.current_sequence_id.next();
            debug!("Entered new touch sequence: {:?}", self.current_sequence_id);
            let active_touch_points = vec![TouchPoint::new(id, point)];
            self.touch_sequence_map.insert(
                self.current_sequence_id,
                TouchSequenceInfo {
                    state: Touching,
                    active_touch_points,
                    handling_touch_move: false,
                    prevent_click: false,
                    prevent_move: TouchMoveAllowed::Pending,
                    pending_touch_move_action: None,
                },
            );
        } else {
            debug!("Touch down in sequence {:?}.", self.current_sequence_id);
            let touch_sequence = self.get_current_touch_sequence_mut();
            touch_sequence
                .active_touch_points
                .push(TouchPoint::new(id, point));
            match touch_sequence.active_touch_points.len() {
                2.. => {
                    touch_sequence.state = MultiTouch;
                },
                0..2 => {
                    unreachable!("Secondary touch_down event with less than 2 fingers active?");
                },
            }
            // Multiple fingers prevent a click.
            touch_sequence.prevent_click = true;
        }
    }

    pub fn on_vsync(&mut self) -> Option<FlingAction> {
        let touch_sequence = self.touch_sequence_map.get_mut(&self.current_sequence_id)?;

        let Flinging { velocity, cursor } = &mut touch_sequence.state else {
            return None;
        };
        if velocity.length().abs() < FLING_MIN_SCREEN_PX {
            touch_sequence.state = Finished;
            // If we were flinging previously, there could still be a touch_up event result
            // coming in after we stopped flinging
            self.try_remove_touch_sequence(self.current_sequence_id);
            None
        } else {
            // TODO: Probably we should multiply with the current refresh rate (and divide on each frame)
            // or save a timestamp to account for a potentially changing display refresh rate.
            *velocity *= FLING_SCALING_FACTOR;
            debug_assert!(velocity.length() <= FLING_MAX_SCREEN_PX);
            Some(FlingAction {
                delta: LayoutVector2D::new(velocity.x, velocity.y),
                cursor: *cursor,
            })
        }
    }

    pub fn on_touch_move(
        &mut self,
        id: TouchId,
        point: Point2D<f32, DevicePixel>,
    ) -> TouchMoveAction {
        // As `TouchHandler` is per `WebViewRenderer` which is per `WebView` we might get a Touch Sequence Move that
        // started with a down on a different webview. As the touch_sequence id is only changed on touch_down this
        // move event gets a touch id which is already cleaned up.
        let Some(touch_sequence) = self.try_get_current_touch_sequence_mut() else {
            return TouchMoveAction::NoAction;
        };
        let idx = match touch_sequence
            .active_touch_points
            .iter_mut()
            .position(|t| t.id == id)
        {
            Some(i) => i,
            None => {
                error!("Got a touchmove event for a non-active touch point");
                return TouchMoveAction::NoAction;
            },
        };
        let old_point = touch_sequence.active_touch_points[idx].point;
        let delta = point - old_point;

        let action = match touch_sequence.touch_count() {
            1 => {
                if let Panning { ref mut velocity } = touch_sequence.state {
                    // TODO: Probably we should track 1-3 more points and use a smarter algorithm
                    *velocity += delta;
                    *velocity /= 2.0;
                    // update the touch point every time when panning.
                    touch_sequence.active_touch_points[idx].point = point;

                    // Scroll offsets are opposite to the direction of finger motion.
                    TouchMoveAction::Scroll(-delta, point)
                } else if delta.x.abs() > TOUCH_PAN_MIN_SCREEN_PX ||
                    delta.y.abs() > TOUCH_PAN_MIN_SCREEN_PX
                {
                    touch_sequence.state = Panning {
                        velocity: Vector2D::new(delta.x, delta.y),
                    };
                    // No clicks should be issued after we transitioned to move.
                    touch_sequence.prevent_click = true;
                    // update the touch point
                    touch_sequence.active_touch_points[idx].point = point;

                    // Scroll offsets are opposite to the direction of finger motion.
                    TouchMoveAction::Scroll(-delta, point)
                } else {
                    // We don't update the touchpoint, so multiple small moves can
                    // accumulate and merge into a larger move.
                    TouchMoveAction::NoAction
                }
            },
            2 => {
                if touch_sequence.state == Pinching ||
                    delta.x.abs() > TOUCH_PAN_MIN_SCREEN_PX ||
                    delta.y.abs() > TOUCH_PAN_MIN_SCREEN_PX
                {
                    touch_sequence.state = Pinching;
                    let (d0, c0) = touch_sequence.pinch_distance_and_center();
                    // update the touch point with the enough distance or pinching.
                    touch_sequence.active_touch_points[idx].point = point;
                    let (d1, c1) = touch_sequence.pinch_distance_and_center();
                    let magnification = d1 / d0;

                    let scroll_delta = c1 - c0 * Scale::new(magnification);

                    // Scroll offsets are opposite to the direction of finger motion.
                    TouchMoveAction::Zoom(magnification, -scroll_delta)
                } else {
                    // We don't update the touchpoint, so multiple small moves can
                    // accumulate and merge into a larger move.
                    TouchMoveAction::NoAction
                }
            },
            _ => {
                touch_sequence.active_touch_points[idx].point = point;
                touch_sequence.state = MultiTouch;
                TouchMoveAction::NoAction
            },
        };
        // If the touch action is not `NoAction` and the first move has not been processed,
        //  set pending_touch_move_action.
        if TouchMoveAction::NoAction != action &&
            touch_sequence.prevent_move == TouchMoveAllowed::Pending
        {
            touch_sequence.update_pending_touch_move_action(action);
        }

        action
    }

    pub fn on_touch_up(&mut self, id: TouchId, point: Point2D<f32, DevicePixel>) {
        let touch_sequence = self.get_current_touch_sequence_mut();
        let old = match touch_sequence
            .active_touch_points
            .iter()
            .position(|t| t.id == id)
        {
            Some(i) => Some(touch_sequence.active_touch_points.swap_remove(i).point),
            None => {
                warn!("Got a touch up event for a non-active touch point");
                None
            },
        };
        match touch_sequence.state {
            Touching => {
                if touch_sequence.prevent_click {
                    touch_sequence.state = Finished;
                } else {
                    touch_sequence.state = PendingClick(point);
                }
            },
            Panning { velocity } => {
                if velocity.length().abs() >= FLING_MIN_SCREEN_PX {
                    // TODO: point != old. Not sure which one is better to take as cursor for flinging.
                    debug!(
                        "Transitioning to Fling. Cursor is {point:?}. Old cursor was {old:?}. \
                            Raw velocity is {velocity:?}."
                    );
                    debug_assert!((point.x as i64) < (i32::MAX as i64));
                    debug_assert!((point.y as i64) < (i32::MAX as i64));
                    let cursor = DeviceIntPoint::new(point.x as i32, point.y as i32);
                    // Multiplying the initial velocity gives the fling a much more snappy feel
                    // and serves well as a poor-mans acceleration algorithm.
                    let velocity = (velocity * 2.0).with_max_length(FLING_MAX_SCREEN_PX);
                    match touch_sequence.prevent_move {
                        TouchMoveAllowed::Allowed => {
                            touch_sequence.state = Flinging { velocity, cursor }
                            // todo: return Touchaction here, or is it sufficient to just
                            // wait for the next vsync?
                        },
                        TouchMoveAllowed::Pending => {
                            touch_sequence.state = PendingFling { velocity, cursor }
                        },
                        TouchMoveAllowed::Prevented => touch_sequence.state = Finished,
                    }
                } else {
                    touch_sequence.state = Finished;
                }
            },
            Pinching => {
                touch_sequence.state = Touching;
            },
            MultiTouch => {
                // We stay in multi-touch mode once we entered it until all fingers are lifted.
                if touch_sequence.active_touch_points.is_empty() {
                    touch_sequence.state = Finished;
                }
            },
            PendingFling { .. } | Flinging { .. } | PendingClick(_) | Finished => {
                error!("Touch-up received, but touch handler already in post-touchup state.")
            },
        }
        #[cfg(debug_assertions)]
        if touch_sequence.active_touch_points.is_empty() {
            debug_assert!(
                touch_sequence.is_finished(),
                "Did not transition to a finished state: {:?}",
                touch_sequence.state
            );
        }
        debug!(
            "Touch up with remaining active touchpoints: {:?}, in sequence {:?}",
            touch_sequence.active_touch_points.len(),
            self.current_sequence_id
        );
    }

    pub fn on_touch_cancel(&mut self, id: TouchId, _point: Point2D<f32, DevicePixel>) {
        // A similar thing with touch move can happen here where the event is coming from a different webview.
        let Some(touch_sequence) = self.try_get_current_touch_sequence_mut() else {
            return;
        };
        match touch_sequence
            .active_touch_points
            .iter()
            .position(|t| t.id == id)
        {
            Some(i) => {
                touch_sequence.active_touch_points.swap_remove(i);
            },
            None => {
                warn!("Got a touchcancel event for a non-active touch point");
                return;
            },
        }
        if touch_sequence.active_touch_points.is_empty() {
            touch_sequence.state = Finished;
        }
    }
}
