/**
 * Example demonstrating the use of the retry mechanism
 */

import {
  executeWithRetry,
  RetryContexts,
  MarineEnvironmentStatus,
  defaultRetryManager
} from '../index';
import { OperationalContext } from '../types/marine-constants';

/**
 * Simulated GPS sensor read that may fail
 */
async function readGPSSensor(): Promise<{ latitude: number; longitude: number }> {
  // Simulate random failures (30% chance)
  if (Math.random() < 0.3) {
    throw new Error('GPS sensor timeout');
  }
  
  // Simulate successful read
  return {
    latitude: 37.7749,
    longitude: -122.4194
  };
}

/**
 * Simulated network request that may fail
 */
async function fetchWeatherData(): Promise<{ temperature: number; windSpeed: number }> {
  // Simulate random failures (50% chance)
  if (Math.random() < 0.5) {
    throw new Error('Network connection lost');
  }
  
  // Simulate successful fetch
  return {
    temperature: 22.5,
    windSpeed: 15.3
  };
}

/**
 * Example of using retry with GPS sensor
 */
async function gpsRetryExample(): Promise<void> {
  console.log('=== GPS Sensor Retry Example ===');
  
  try {
    // Set up marine environment
    const environment: MarineEnvironmentStatus = {
      seaState: 'moderate',
      weather: 'cloudy',
      windSpeed: 12,
      temperature: 18,
      powerStatus: 'normal',
      connectivityQuality: 0.8,
      expectedFailureRate: 1.2,
      recommendedTimeoutMultiplier: 1.1,
      criticalOperationsOnly: false
    };
    
    // Update retry manager with current environment
    defaultRetryManager.updateMarineEnvironment(environment);
    
    // Execute GPS read with retry
    console.log('Attempting to read GPS sensor with retry...');
    const result = await executeWithRetry(
      readGPSSensor,
      RetryContexts.navigationSensor('gps-position', OperationalContext.SAILING)
    );
    
    if (result.success) {
      console.log('GPS read successful:', result.data);
      console.log(`Took ${result.retryCount} retries`);
      if (result.retryDelays.length > 0) {
        console.log('Retry delays (ms):', result.retryDelays);
      }
    } else {
      console.error('GPS read failed after retries:', result.error?.message);
      console.log(`Failed after ${result.retryCount} retries`);
      console.log('Retry delays (ms):', result.retryDelays);
    }
    
    // Show metrics
    console.log('Retry metrics:', defaultRetryManager.getMetrics());
    
  } catch (error) {
    console.error('Unexpected error:', error);
  }
}

/**
 * Example of using retry with network operations
 */
async function networkRetryExample(): Promise<void> {
  console.log('\n=== Network Operation Retry Example ===');
  
  try {
    // Set up marine environment with poor connectivity
    const environment: MarineEnvironmentStatus = {
      seaState: 'rough',
      weather: 'rain',
      windSpeed: 25,
      temperature: 15,
      powerStatus: 'conservation',
      connectivityQuality: 0.3, // Poor connectivity
      expectedFailureRate: 2.0,
      recommendedTimeoutMultiplier: 1.5,
      criticalOperationsOnly: false
    };
    
    // Update retry manager with current environment
    defaultRetryManager.updateMarineEnvironment(environment);
    
    // Execute network request with retry
    console.log('Attempting to fetch weather data with retry...');
    const result = await executeWithRetry(
      fetchWeatherData,
      RetryContexts.networkOperation('weather-api', OperationalContext.SAILING)
    );
    
    if (result.success) {
      console.log('Weather data fetch successful:', result.data);
      console.log(`Took ${result.retryCount} retries`);
      if (result.retryDelays.length > 0) {
        console.log('Retry delays (ms):', result.retryDelays);
      }
    } else {
      console.error('Weather data fetch failed after retries:', result.error?.message);
      console.log(`Failed after ${result.retryCount} retries`);
      console.log('Retry delays (ms):', result.retryDelays);
    }
    
    // Show metrics
    console.log('Retry metrics:', defaultRetryManager.getMetrics());
    
  } catch (error) {
    console.error('Unexpected error:', error);
  }
}

/**
 * Example of retry behavior in emergency context
 */
async function emergencyContextExample(): Promise<void> {
  console.log('\n=== Emergency Context Retry Example ===');
  
  try {
    // Set up emergency marine environment
    const environment: MarineEnvironmentStatus = {
      seaState: 'very_rough',
      weather: 'storm',
      windSpeed: 40,
      temperature: 10,
      powerStatus: 'critical',
      connectivityQuality: 0.1,
      expectedFailureRate: 3.0,
      recommendedTimeoutMultiplier: 0.5, // Faster timeouts in emergency
      criticalOperationsOnly: true
    };
    
    // Update retry manager with current environment
    defaultRetryManager.updateMarineEnvironment(environment);
    
    // Execute GPS read with retry in emergency context
    console.log('Attempting to read GPS sensor in emergency context...');
    const result = await executeWithRetry(
      readGPSSensor,
      RetryContexts.navigationSensor('gps-position', OperationalContext.EMERGENCY)
    );
    
    if (result.success) {
      console.log('GPS read successful:', result.data);
      console.log(`Took ${result.retryCount} retries`);
    } else {
      console.error('GPS read failed:', result.error?.message);
      console.log(`Retries attempted: ${result.retryCount}`);
      console.log('Note: Retries are disabled in emergency context');
    }
    
    // Show metrics
    console.log('Retry metrics:', defaultRetryManager.getMetrics());
    
  } catch (error) {
    console.error('Unexpected error:', error);
  }
}

/**
 * Run all examples
 */
async function runAllExamples(): Promise<void> {
  await gpsRetryExample();
  await networkRetryExample();
  await emergencyContextExample();
  
  console.log('\n=== Final Retry Metrics ===');
  console.log(defaultRetryManager.getMetrics());
}

// Run the examples
runAllExamples().catch(console.error);
