// Touch Interactions Composable for Mobile DMS
// Provides swipe gestures, touch controls, and mobile enhancements

import { ref, onMounted, onUnmounted, nextTick, readonly } from 'vue';

export const useTouchInteractions = (options = {}) => {
  // Default configuration
  const defaultOptions = {
    threshold: 50,        // Minimum distance for swipe
    velocity: 0.3,        // Minimum velocity for swipe
    timeThreshold: 500,   // Maximum time for swipe
    preventScroll: false, // Prevent scroll during swipe
    enablePinch: false,   // Enable pinch-to-zoom
    enableRotation: false, // Enable rotation
    ...options
  };

  // Touch state
  const touchState = ref({
    isSupported: false,
    isSwiping: false,
    startX: 0,
    startY: 0,
    currentX: 0,
    currentY: 0,
    startTime: 0,
    direction: null,
    distance: 0,
    velocity: 0
  });

  // Multi-touch state
  const multiTouchState = ref({
    isMultiTouch: false,
    initialDistance: 0,
    currentDistance: 0,
    scale: 1,
    rotation: 0
  });

  // Gesture detection
  const gestures = ref({
    swipeLeft: false,
    swipeRight: false,
    swipeUp: false,
    swipeDown: false,
    pinch: false,
    spread: false,
    rotate: false
  });

  // Event callbacks
  const callbacks = ref({
    onSwipeStart: null,
    onSwipeMove: null,
    onSwipeEnd: null,
    onSwipeLeft: null,
    onSwipeRight: null,
    onSwipeUp: null,
    onSwipeDown: null,
    onPinchStart: null,
    onPinchMove: null,
    onPinchEnd: null,
    onRotateStart: null,
    onRotateMove: null,
    onRotateEnd: null,
    onTap: null,
    onDoubleTap: null,
    onLongPress: null
  });

  // Utility functions
  const getDistance = (touches) => {
    if (touches.length < 2) return 0;
    const dx = touches[0].clientX - touches[1].clientX;
    const dy = touches[0].clientY - touches[1].clientY;
    return Math.sqrt(dx * dx + dy * dy);
  };

  const getAngle = (touches) => {
    if (touches.length < 2) return 0;
    const dx = touches[1].clientX - touches[0].clientX;
    const dy = touches[1].clientY - touches[0].clientY;
    return Math.atan2(dy, dx) * 180 / Math.PI;
  };

  const getDirection = (startX, startY, endX, endY) => {
    const dx = endX - startX;
    const dy = endY - startY;
    
    if (Math.abs(dx) > Math.abs(dy)) {
      return dx > 0 ? 'right' : 'left';
    } else {
      return dy > 0 ? 'down' : 'up';
    }
  };

  const getVelocity = (distance, time) => {
    return time > 0 ? distance / time : 0;
  };

  // Touch event handlers
  const handleTouchStart = (event) => {
    const touch = event.touches[0];
    const now = Date.now();

    touchState.value = {
      ...touchState.value,
      isSwiping: true,
      startX: touch.clientX,
      startY: touch.clientY,
      currentX: touch.clientX,
      currentY: touch.clientY,
      startTime: now,
      direction: null,
      distance: 0,
      velocity: 0
    };

    // Multi-touch handling
    if (event.touches.length > 1 && defaultOptions.enablePinch) {
      multiTouchState.value = {
        isMultiTouch: true,
        initialDistance: getDistance(event.touches),
        currentDistance: getDistance(event.touches),
        scale: 1,
        rotation: getAngle(event.touches)
      };
      
      callbacks.value.onPinchStart?.(multiTouchState.value);
    }

    callbacks.value.onSwipeStart?.(touchState.value);

    if (defaultOptions.preventScroll) {
      event.preventDefault();
    }
  };

  const handleTouchMove = (event) => {
    if (!touchState.value.isSwiping) return;

    const touch = event.touches[0];
    const currentX = touch.clientX;
    const currentY = touch.clientY;
    
    const deltaX = currentX - touchState.value.startX;
    const deltaY = currentY - touchState.value.startY;
    const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    
    touchState.value = {
      ...touchState.value,
      currentX,
      currentY,
      distance,
      direction: getDirection(
        touchState.value.startX,
        touchState.value.startY,
        currentX,
        currentY
      )
    };

    // Multi-touch handling
    if (event.touches.length > 1 && multiTouchState.value.isMultiTouch) {
      const currentDistance = getDistance(event.touches);
      const currentRotation = getAngle(event.touches);
      
      multiTouchState.value = {
        ...multiTouchState.value,
        currentDistance,
        scale: currentDistance / multiTouchState.value.initialDistance,
        rotation: currentRotation - multiTouchState.value.rotation
      };
      
      callbacks.value.onPinchMove?.(multiTouchState.value);
    }

    callbacks.value.onSwipeMove?.(touchState.value);

    if (defaultOptions.preventScroll) {
      event.preventDefault();
    }
  };

  const handleTouchEnd = (event) => {
    if (!touchState.value.isSwiping) return;

    const endTime = Date.now();
    const duration = endTime - touchState.value.startTime;
    const velocity = getVelocity(touchState.value.distance, duration);
    
    touchState.value = {
      ...touchState.value,
      isSwiping: false,
      velocity
    };

    // Determine if it's a valid swipe
    const isValidSwipe = 
      touchState.value.distance >= defaultOptions.threshold &&
      velocity >= defaultOptions.velocity &&
      duration <= defaultOptions.timeThreshold;

    if (isValidSwipe) {
      // Reset gesture state
      Object.keys(gestures.value).forEach(key => {
        gestures.value[key] = false;
      });

      // Set current gesture
      switch (touchState.value.direction) {
        case 'left':
          gestures.value.swipeLeft = true;
          callbacks.value.onSwipeLeft?.(touchState.value);
          break;
        case 'right':
          gestures.value.swipeRight = true;
          callbacks.value.onSwipeRight?.(touchState.value);
          break;
        case 'up':
          gestures.value.swipeUp = true;
          callbacks.value.onSwipeUp?.(touchState.value);
          break;
        case 'down':
          gestures.value.swipeDown = true;
          callbacks.value.onSwipeDown?.(touchState.value);
          break;
      }
    }

    // Multi-touch end
    if (multiTouchState.value.isMultiTouch) {
      callbacks.value.onPinchEnd?.(multiTouchState.value);
      multiTouchState.value.isMultiTouch = false;
    }

    callbacks.value.onSwipeEnd?.(touchState.value);
  };

  // Tap detection
  let tapTimeout = null;
  let tapCount = 0;
  let longPressTimeout = null;

  const handleTap = (event) => {
    const touch = event.touches[0] || event.changedTouches[0];
    
    // Long press detection
    longPressTimeout = setTimeout(() => {
      callbacks.value.onLongPress?.({
        x: touch.clientX,
        y: touch.clientY,
        target: event.target
      });
    }, 500);

    // Double tap detection
    tapCount++;
    
    if (tapCount === 1) {
      tapTimeout = setTimeout(() => {
        if (tapCount === 1) {
          callbacks.value.onTap?.({
            x: touch.clientX,
            y: touch.clientY,
            target: event.target
          });
        }
        tapCount = 0;
      }, 300);
    } else if (tapCount === 2) {
      clearTimeout(tapTimeout);
      clearTimeout(longPressTimeout);
      callbacks.value.onDoubleTap?.({
        x: touch.clientX,
        y: touch.clientY,
        target: event.target
      });
      tapCount = 0;
    }
  };

  const handleTouchCancel = () => {
    touchState.value.isSwiping = false;
    multiTouchState.value.isMultiTouch = false;
    clearTimeout(tapTimeout);
    clearTimeout(longPressTimeout);
  };

  // Setup touch interactions
  const setupTouchInteractions = (element) => {
    if (!element) return;

    // Check for touch support
    touchState.value.isSupported = 'ontouchstart' in window;

    if (touchState.value.isSupported) {
      element.addEventListener('touchstart', handleTouchStart, { passive: !defaultOptions.preventScroll });
      element.addEventListener('touchmove', handleTouchMove, { passive: !defaultOptions.preventScroll });
      element.addEventListener('touchend', handleTouchEnd, { passive: true });
      element.addEventListener('touchcancel', handleTouchCancel, { passive: true });
      
      // Tap events
      element.addEventListener('touchstart', handleTap, { passive: true });
    }

    return () => {
      if (element && touchState.value.isSupported) {
        element.removeEventListener('touchstart', handleTouchStart);
        element.removeEventListener('touchmove', handleTouchMove);
        element.removeEventListener('touchend', handleTouchEnd);
        element.removeEventListener('touchcancel', handleTouchCancel);
        element.removeEventListener('touchstart', handleTap);
      }
    };
  };

  // Register callback functions
  const onSwipeStart = (callback) => { callbacks.value.onSwipeStart = callback; };
  const onSwipeMove = (callback) => { callbacks.value.onSwipeMove = callback; };
  const onSwipeEnd = (callback) => { callbacks.value.onSwipeEnd = callback; };
  const onSwipeLeft = (callback) => { callbacks.value.onSwipeLeft = callback; };
  const onSwipeRight = (callback) => { callbacks.value.onSwipeRight = callback; };
  const onSwipeUp = (callback) => { callbacks.value.onSwipeUp = callback; };
  const onSwipeDown = (callback) => { callbacks.value.onSwipeDown = callback; };
  const onPinchStart = (callback) => { callbacks.value.onPinchStart = callback; };
  const onPinchMove = (callback) => { callbacks.value.onPinchMove = callback; };
  const onPinchEnd = (callback) => { callbacks.value.onPinchEnd = callback; };
  const onTap = (callback) => { callbacks.value.onTap = callback; };
  const onDoubleTap = (callback) => { callbacks.value.onDoubleTap = callback; };
  const onLongPress = (callback) => { callbacks.value.onLongPress = callback; };

  // DMS-specific touch interactions
  const dmsInteractions = {
    // Swipe to delete
    setupSwipeToDelete: (element, onDelete) => {
      const cleanup = setupTouchInteractions(element);
      onSwipeLeft(() => {
        element.classList.add('swipe-delete-active');
        onDelete?.();
      });
      return cleanup;
    },

    // Pull to refresh
    setupPullToRefresh: (element, onRefresh) => {
      let refreshTriggered = false;
      const cleanup = setupTouchInteractions(element);
      
      onSwipeDown((state) => {
        if (state.distance > 100 && !refreshTriggered) {
          refreshTriggered = true;
          onRefresh?.();
          setTimeout(() => {
            refreshTriggered = false;
          }, 2000);
        }
      });
      
      return cleanup;
    },

    // Pinch to zoom for document preview
    setupPinchZoom: (element, onZoom) => {
      const cleanup = setupTouchInteractions(element);
      onPinchMove((state) => {
        onZoom?.(state.scale);
      });
      return cleanup;
    },

    // Long press for context menu
    setupContextMenu: (element, onContext) => {
      const cleanup = setupTouchInteractions(element);
      onLongPress((state) => {
        onContext?.(state);
      });
      return cleanup;
    }
  };

  // Haptic feedback (if supported)
  const hapticFeedback = {
    light: () => {
      if (navigator.vibrate) {
        navigator.vibrate(10);
      }
    },
    
    medium: () => {
      if (navigator.vibrate) {
        navigator.vibrate(20);
      }
    },
    
    heavy: () => {
      if (navigator.vibrate) {
        navigator.vibrate([30, 10, 30]);
      }
    },
    
    success: () => {
      if (navigator.vibrate) {
        navigator.vibrate([10, 5, 10]);
      }
    },
    
    error: () => {
      if (navigator.vibrate) {
        navigator.vibrate([50, 25, 50]);
      }
    }
  };

  return {
    // State
    touchState: readonly(touchState),
    multiTouchState: readonly(multiTouchState),
    gestures: readonly(gestures),
    
    // Setup
    setupTouchInteractions,
    
    // Event registration
    onSwipeStart,
    onSwipeMove,
    onSwipeEnd,
    onSwipeLeft,
    onSwipeRight,
    onSwipeUp,
    onSwipeDown,
    onPinchStart,
    onPinchMove,
    onPinchEnd,
    onTap,
    onDoubleTap,
    onLongPress,
    
    // DMS-specific
    dmsInteractions,
    
    // Utilities
    hapticFeedback,
    
    // Configuration
    options: defaultOptions
  };
}; 