# Copyright (C) 2016  Pachol, Vojtěch <pacholick@gmail.com>
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program.  If not, see
# <http://www.gnu.org/licenses/>.

import re
import math

from commacalc.extra import sign


_SYMBOLS = {
    'k': "1000",
    'M': "1000000",
    'G': "1000000000",
    'T': "1000000000000",
    'P': "1000000000000000",

    'm': "0.001",
    'μ': "0.000001",
    'n': "0.000000001",
    'p': "0.000000000001",
    'f': "0.000000000000001",

    '°': "(π/180)",
}


def replace_symbols(input_):
    """replace 123k with 1000*123"""
    for symbol, value in _SYMBOLS.items():
        input_ = re.sub(
            r'(\d+){}'.format(symbol),
            r'\1*{}'.format(value),
            input_
        )
    return input_


def from_fahrenheit(fahrenheit):
    """Convert Fahrenheits to Centigrade."""
    return (fahrenheit - 32)*5/9


C = from_fahrenheit


def to_fahrenheit(c):
    """Convert Centigrade to Fahrenheits."""
    return c*9/5 + 32


def prefix(x, dimension=1):
    """Give the number an appropriate SI prefix.

    :param x:   Too big or too small number.
    :returns:   String containing a number between 1 and 1000 and SI prefix.
    """
    if x == 0:
        return "0  "

    l = math.floor(math.log10(abs(x)))
    if abs(l) > 24:
        l = sign(l, value=24)

    div, mod = divmod(l, 3*dimension)
    # return "%.3g %s" % (x * 10**(-l + l % 3), " kMGTPEZYyzafpnµm"[l//3])
    return "{:.3g} {}".format(x*10**(-l + mod), " kMGTPEZYyzafpnµm"[div])


# maths
π = math.pi
φ = (1 + math.sqrt(5))/2

# physics
c = 299792458
"""Speed of light in vacuum (exact) [ m s⁻¹ ]"""
G = 6.6738480e-11
"""Gravitational constant [ m³ kg⁻¹ s⁻² ]"""
h = 6.6260695729e-34
"""Planck constant [ J s ]"""
ħ = h/(2*math.pi)
"""Reduced Planck constant [ J s ]"""
k_e = 8.9875517873681764e9
"""Coulomb constant (exact) [ kg m³ s⁻² C⁻² ]"""
k_B = 1.380648813e-23
"""Boltzmann constant [ J K⁻¹ ]"""

eV = 1.60217656535e-19
"""Electronvolt"""


# imperial units to metres (exact)
inch = 0.0254
foot = ft = 0.3048
yard = yd = 0.9144
mile = mi = 1609.344
acre = ac = 4046.8564224
pound = lb = 0.45359237
barrel = 0.15897    # (not exact)


# time
days_in_year = 365.242189
seconds_in_day = 86400
seconds_in_year = days_in_year*seconds_in_day


if __name__ == "__main__":
    print(prefix(0.9, 2))
