import math

Vc = 299792458
Ga = 9.80665
HYDROGEN_FUSION_EFFICIENCY = 0.0072320773061889


def cal_dv(isp, dry_mass, fuel_mass):
    return math.log((fuel_mass + dry_mass) / dry_mass) * Ga * isp


def cal_fuel_burned(isp, thrust, duration):
    """
    calculate the amount of fuel burned in duration. In KG
    :param isp: in seconds
    :param thrust: in KN
    :param duration: in seconds
    :return:
    """
    fuel_burned = duration * (thrust * 1000 / isp / Ga)
    fuel_burned *= pow(1 - pow(isp * Ga / Vc, 2), 0.5)   # Adjust for relativity speed
    return fuel_burned


def cal_burn_time(isp, thrust, fuel_mass):
    """
    calculate the burn time
    :param isp:
    :param thrust:
    :param fuel_mass:
    :return:
    """
    fuel_burned = thrust * 1000 / isp / Ga
    return fuel_mass / fuel_burned


def cal_kinetic_energy(isp, thrust, duration=1, engine_efficiency=1):
    """

    :param isp: In second
    :param thrust: In KN
    :param duration: In second
    :param engine_efficiency:
    :return:
    """
    fuel_burned = cal_fuel_burned(isp, thrust, duration)
    exhaust_velocity = isp * Ga
    ek = fuel_burned * (exhaust_velocity ** 2) / (1-(exhaust_velocity/Vc)**2 + pow(1-(exhaust_velocity/Vc)**2, 0.5))
    return ek / engine_efficiency


def cal_fusion_input_mass(reactor_efficiency, wattage):
    """
    calculate the amount of fusion fuel needed per second based on the fusion efficiency and power requirement
    :param reactor_efficiency:
    :param wattage:
    :return: fusion mass in kg
    """

    mass = wattage / (Vc ** 2)
    return mass / reactor_efficiency


def cal_total_mass_consumption(isp, thrust, reactor_efficiency, engine_efficiency, flag=False):
    fuel_burned = cal_fuel_burned(isp, thrust, 1)
    reactor_mass = cal_fusion_input_mass(reactor_efficiency, cal_kinetic_energy(isp, thrust, 1, engine_efficiency))
    total_mass = fuel_burned + reactor_mass
    if flag:
        print(fuel_burned, reactor_mass)
    return total_mass


def cal_best_isp_relativity_speed(reactor_efficiency, engine_efficiency, thrust):
    best_isp = pow(1 - 1/(pow(reactor_efficiency*engine_efficiency + 1, 2)), 0.5) * Vc / Ga
    mass_flow_rate = cal_total_mass_consumption(best_isp, thrust, reactor_efficiency, engine_efficiency, False)
    return best_isp, mass_flow_rate


def cal_dv_step_by_step_fusion(reactor_efficiency, engine_efficiency, thrust, dry_mass, fuel_mass, interval=1):
    """
    calculate the delta v of a fusion-tech based spacecraft.
    :param reactor_efficiency:
    :param engine_efficiency:
    :param thrust:
    :param dry_mass:
    :param fuel_mass:
    :param interval:

    :return:
    """
    total_mass = dry_mass + fuel_mass
    isp, fuel_flow_rate = cal_best_isp_relativity_speed(reactor_efficiency, engine_efficiency, thrust)
    new_fuel_mass, new_total_mass = fuel_mass, total_mass
    delta_v = 0
    while new_fuel_mass > 0:
        delta_v += thrust * 1000 * interval / new_total_mass
        total_mass -= interval * fuel_flow_rate
        new_fuel_mass -= interval * fuel_flow_rate
    return delta_v


if __name__ == '__main__':
    merlin_fuel_burned = cal_fuel_burned(314.3, 931, 1)
    merlin_kinetic_energy = cal_kinetic_energy(314.3, 931, 1, 1)
    theoretical_kerosene_burn_heat = 0.27785743459149853 * merlin_fuel_burned * 43.11 * 1000000

    raptor_fuel_burned = cal_fuel_burned(355, 2450, 1)
    raptor_kinetic_energy = cal_kinetic_energy(355, 2450, 1, 1)
    theoretical_methane_burn_heat = 0.20836197008574792 * raptor_fuel_burned * 55 * 1000000


    # first_stage_fuel = cal_fuel_burned(328, 812.05*4, 148)
    # x = cal_fuel_burned(333, 80, 610) + cal_fuel_burned(350, 823.2, 148)
    # x = cal_dv(338.2, 55000, 70000)
    # xx = cal_fuel_burned(21000, 400, 1)

    print(cal_dv(298.7, 12.48, 13.52))

    x = cal_kinetic_energy(350, 2450, 1, 1)
    # x = cal_kinetic_energy(314.3, 931, 1, 1)
    y = cal_kinetic_energy(21000, 800, 1, 1)
    print(y / x)
    y = cal_fusion_input_mass(HYDROGEN_FUSION_EFFICIENCY * 0.1, x)

    test = cal_burn_time(310, 1.95, 3)
    ship_dry_mass = 2000*1000   # 2000t
    ship_fuel_mass = 500*1000   # 500t
    main_engine_thrust = 10000  # 10000KN
    ship_isp, flow_rate = cal_best_isp_relativity_speed(reactor_efficiency=0.45, engine_efficiency=0.8,
                                                        thrust=main_engine_thrust)
    exhaust_velocity = ship_isp * Ga / Vc
    dv = cal_dv(ship_isp, ship_dry_mass + ship_fuel_mass / 2, ship_fuel_mass / 2)
    dv2 = cal_dv_step_by_step_fusion(reactor_efficiency=0.45, engine_efficiency=0.8, thrust=main_engine_thrust,
                                     dry_mass=ship_dry_mass, fuel_mass=ship_fuel_mass, interval=1)
    burn_time = ship_fuel_mass / flow_rate / 86400
    x = 27632994.05705879

    xxx = cal_fuel_burned(335.1, 1339.48, 174)
    print('done')



