# Ruby Calculator - Interactive calculator built with Ruby on Rails
# Author: RSK World (Molla Samser, Founder | Rima Khatun, Designer & Tester)
# Contact: help@rskworld.in | +91 93305 39277
# Website: https://rskworld.in
# Year: 2026
# Description: Build a fully functional calculator using Ruby on Rails with modern UI

class Converter
  include HTTParty
  
  base_uri 'https://api.exchangerate-api.com/v4/latest'
  
  # Currency conversion rates (static fallback)
  CURRENCY_RATES = {
    'USD' => 1.0,
    'EUR' => 0.85,
    'GBP' => 0.73,
    'JPY' => 110.0,
    'INR' => 74.0,
    'CAD' => 1.25,
    'AUD' => 1.35,
    'CHF' => 0.92,
    'CNY' => 6.45,
    'SEK' => 8.60,
    'NZD' => 1.40,
    'MXN' => 20.0,
    'SGD' => 1.35,
    'HKD' => 7.80,
    'NOK' => 8.50,
    'KRW' => 1180.0,
    'TRY' => 8.50,
    'RUB' => 74.0,
    'BRL' => 5.20,
    'ZAR' => 15.0
  }
  
  # Unit conversion factors
  UNIT_CONVERSIONS = {
    length: {
      meter: { factor: 1.0, symbol: 'm' },
      kilometer: { factor: 1000.0, symbol: 'km' },
      centimeter: { factor: 0.01, symbol: 'cm' },
      millimeter: { factor: 0.001, symbol: 'mm' },
      mile: { factor: 1609.34, symbol: 'mi' },
      yard: { factor: 0.9144, symbol: 'yd' },
      foot: { factor: 0.3048, symbol: 'ft' },
      inch: { factor: 0.0254, symbol: 'in' }
    },
    weight: {
      kilogram: { factor: 1.0, symbol: 'kg' },
      gram: { factor: 0.001, symbol: 'g' },
      milligram: { factor: 0.000001, symbol: 'mg' },
      pound: { factor: 0.453592, symbol: 'lb' },
      ounce: { factor: 0.0283495, symbol: 'oz' },
      ton: { factor: 1000.0, symbol: 't' }
    },
    temperature: {
      celsius: { symbol: '°C' },
      fahrenheit: { symbol: '°F' },
      kelvin: { symbol: 'K' }
    },
    volume: {
      liter: { factor: 1.0, symbol: 'L' },
      milliliter: { factor: 0.001, symbol: 'mL' },
      gallon: { factor: 3.78541, symbol: 'gal' },
      quart: { factor: 0.946353, symbol: 'qt' },
      pint: { factor: 0.473176, symbol: 'pt' },
      cup: { factor: 0.236588, symbol: 'cup' },
      fluid_ounce: { factor: 0.0295735, symbol: 'fl oz' }
    },
    area: {
      square_meter: { factor: 1.0, symbol: 'm²' },
      square_kilometer: { factor: 1000000.0, symbol: 'km²' },
      square_centimeter: { factor: 0.0001, symbol: 'cm²' },
      hectare: { factor: 10000.0, symbol: 'ha' },
      acre: { factor: 4046.86, symbol: 'acre' },
      square_foot: { factor: 0.092903, symbol: 'ft²' },
      square_inch: { factor: 0.00064516, symbol: 'in²' }
    },
    speed: {
      meter_per_second: { factor: 1.0, symbol: 'm/s' },
      kilometer_per_hour: { factor: 0.277778, symbol: 'km/h' },
      mile_per_hour: { factor: 0.44704, symbol: 'mph' },
      knot: { factor: 0.514444, symbol: 'kn' }
    },
    data: {
      byte: { factor: 1.0, symbol: 'B' },
      kilobyte: { factor: 1024.0, symbol: 'KB' },
      megabyte: { factor: 1048576.0, symbol: 'MB' },
      gigabyte: { factor: 1073741824.0, symbol: 'GB' },
      terabyte: { factor: 1099511627776.0, symbol: 'TB' },
      bit: { factor: 0.125, symbol: 'bit' },
      kilobit: { factor: 128.0, symbol: 'Kb' },
      megabit: { factor: 131072.0, symbol: 'Mb' },
      gigabit: { factor: 134217728.0, symbol: 'Gb' }
    }
  }
  
  def self.convert_currency(amount, from_currency, to_currency)
    from_rate = CURRENCY_RATES[from_currency.upcase]
    to_rate = CURRENCY_RATES[to_currency.upcase]
    
    return nil unless from_rate && to_rate
    
    # Convert to USD first, then to target currency
    usd_amount = amount / from_rate
    result = usd_amount * to_rate
    
    result.round(4)
  end
  
  def self.convert_unit(amount, from_unit, to_unit, category)
    return nil unless UNIT_CONVERSIONS[category]
    
    if category == :temperature
      convert_temperature(amount, from_unit, to_unit)
    else
      from_data = UNIT_CONVERSIONS[category][from_unit.to_sym]
      to_data = UNIT_CONVERSIONS[category][to_unit.to_sym]
      
      return nil unless from_data && to_data
      
      # Convert to base unit first, then to target unit
      base_amount = amount * from_data[:factor]
      result = base_amount / to_data[:factor]
      
      result.round(6)
    end
  end
  
  def self.convert_temperature(amount, from_unit, to_unit)
    case from_unit.downcase
    when 'celsius'
      case to_unit.downcase
      when 'fahrenheit' then (amount * 9/5) + 32
      when 'kelvin' then amount + 273.15
      else amount
      end
    when 'fahrenheit'
      case to_unit.downcase
      when 'celsius' then (amount - 32) * 5/9
      when 'kelvin' then (amount - 32) * 5/9 + 273.15
      else amount
      end
    when 'kelvin'
      case to_unit.downcase
      when 'celsius' then amount - 273.15
      when 'fahrenheit' then (amount - 273.15) * 9/5 + 32
      else amount
      end
    else
      amount
    end.round(2)
  end
  
  def self.get_available_currencies
    CURRENCY_RATES.keys.sort
  end
  
  def self.get_available_units(category)
    return [] unless UNIT_CONVERSIONS[category.to_sym]
    UNIT_CONVERSIONS[category.to_sym].keys.map(&:to_s).sort
  end
  
  def self.get_available_categories
    UNIT_CONVERSIONS.keys.map(&:to_s).sort
  end
end
