# -*- coding: utf-8 -*-

import pytest

import os
import yaml
import dingguo
import difflib
import datetime

def get_figure_a():
    return dingguo.Figure(12.3, u'km')

def get_figure_b():
    return dingguo.Figure(12300, u'米')

def get_sum_a():
    return dingguo.Sum(1.23, u'EUR')

def get_sum_b():
    return dingguo.Sum(20.45, u'€')

def get_item_a():
    return dingguo.Item(
            name = u'item a',
            price_brutto = get_sum_a(),
            )

def get_item_b():
    return dingguo.Item(
            name = u'item β',
            price_brutto = get_sum_b(),
            )

def get_article():
    return dingguo.Article(
            authors = ['a', 'b'],
            depth = dingguo.ScalarFigure(12.3, u'dm'),
            features = u'supergeil',
            height = dingguo.ScalarFigure(123., u'cm'),
            maximum_load = dingguo.ScalarFigure(40., u'kg'),
            name = u'article name',
            price_brutto = get_sum_a(),
            product_id = u'0815',
            quantity = 1,
            reseller = u'seller',
            shipper = u'shipper',
            state = u'goood',
            width = dingguo.ScalarFigure(1.23, u'm'),
            )

def get_transportation():
    return dingguo.Transportation(
            name = u'ticket',
            price_brutto = get_sum_a(),
            departure_point = u'home',
            destination_point = u'city',
            distance = dingguo.Distance(3.21, u'km'),
            )

def get_taxi_ride():
    return dingguo.TaxiRide(
            name = u'taxi ride',
            price_brutto = get_sum_a(),
            departure_point = u'home',
            destination_point = u'city',
            distance = dingguo.Distance(3.21, u'km'),
            driver = u'driver',
            arrival_time = datetime.datetime(2016, 5, 2, 18, 10),
            departure_time = datetime.datetime(2016, 5, 2, 18, 25),
            )

def get_discount_a():
    return dingguo.Discount(
            name = u'discount a',
            amount = get_sum_a(),
            )

def get_discount_b():
    return dingguo.Discount(
            name = u'discount β',
            amount = get_sum_b(),
            )

def get_order_a(items = True, discounts = True):
    order = dingguo.Order(
            platform = u'platformπ',
            order_id = u'id',
            order_date = datetime.datetime(2016, 5, 8, 0, 18, 17),
            customer_id = u'customer',
            )
    if items:
        order.items.append(get_item_a())
        order.items.append(get_item_b())
    if discounts:
        order.discounts.append(get_discount_a())
        order.discounts.append(get_discount_b())
    return order

def get_order_b():
    order = dingguo.Order(
            platform = u'platformπ',
            order_id = u'order_b',
            order_date = datetime.datetime(2015, 5, 8, 0, 18, 17),
            )
    return order

def get_order_c():
    order = dingguo.Order(
            platform = u'γάμμα',
            order_id = u'order_βήτα',
            order_date = datetime.datetime(2014, 5, 8, 0, 18, 17),
            customer_id = u'ρώ',
            )
    return order

def get_distance():
    return dingguo.Distance(2.4142, u'km')

def get_order_registry():
    registry = dingguo.OrderRegistry()
    registry.register(get_order_a(items = False, discounts = False))
    registry.register(get_order_b())
    registry.register(get_order_c())
    return registry

def to_yaml(data):
    return yaml.dump(data, default_flow_style = False, allow_unicode = True).decode('utf-8')

def yaml_diff(a, b):
    return '\n'.join(difflib.ndiff(
        to_yaml(a).split('\n'),
        to_yaml(b).split('\n'),
        ))

def test_figure_to_yaml():
    assert to_yaml(get_figure_a()) == u"""!figure
unit: km
value: 12.3
"""

def test_figure_to_yaml_unicode():
    assert to_yaml(get_figure_b()) == u"""!figure
unit: 米
value: 12300
"""

def test_figure_from_yaml():
    assert get_figure_a() == yaml.load(u"""!figure
unit: km
value: 12.3
""")

def test_figure_to_yaml_unicode():
    assert get_figure_b() == yaml.load(u"""!figure
unit: 米
value: 12300
""")

def test_sum_to_yaml_a():
    assert to_yaml(get_sum_a()) == u"!sum '1.23 EUR'\n"

def test_sum_to_yaml_b():
    assert to_yaml(get_sum_b()) == u"!sum '20.45 EUR'\n"

def test_sum_from_yaml_a():
    assert get_sum_a() == yaml.load(u"!sum 1.23 EUR")

def test_sum_from_yaml_a_sign():
    assert get_sum_a() == yaml.load(u"!sum 1.23 €")

def test_sum_from_yaml_a_quotes():
    assert get_sum_a() == yaml.load(u"!sum '1.23 EUR'")

def test_item_to_yaml_a():
    assert to_yaml(get_item_a()) == u"""!item
name: item a
price_brutto: !sum '1.23 EUR'
"""

def test_item_to_yaml_b():
    assert to_yaml(get_item_b()) == u"""!item
name: item β
price_brutto: !sum '20.45 EUR'
"""

def test_item_from_yaml_a():
    assert get_item_a() == yaml.load(u"""!item
name: item a
price_brutto: !sum '1.23 EUR'
""")

def test_item_from_yaml_b():
    assert get_item_b() == yaml.load(u"""!item
name: item β
price_brutto: !sum '20.45 EUR'
""")

def test_discount_to_yaml_a():
    assert to_yaml(get_discount_a()) == u"""!discount
amount: !sum '1.23 EUR'
name: discount a
"""

def test_discount_to_yaml_b():
    assert to_yaml(get_discount_b()) == u"""!discount
amount: !sum '20.45 EUR'
name: discount β
"""

def test_discount_from_yaml_a():
    assert get_discount_a() == yaml.load(u"""!discount
name: discount a
amount: !sum '1.23 EUR'
""")

def test_discount_from_yaml_b():
    assert get_discount_b() == yaml.load(u"""!discount
name: discount β
amount: !sum '20.45 EUR'
""")

def test_order_to_yaml():
    assert to_yaml(get_order_a()) == u"""!order
customer_id: customer
discounts:
- !discount
  amount: !sum '1.23 EUR'
  name: discount a
- !discount
  amount: !sum '20.45 EUR'
  name: discount β
items:
- !item
  name: item a
  price_brutto: !sum '1.23 EUR'
- !item
  name: item β
  price_brutto: !sum '20.45 EUR'
order_date: 2016-05-08
order_id: id
platform: platformπ
"""

def test_order_from_yaml():
    order_loaded = yaml.load(u"""!order
customer_id: customer
discounts:
- !discount
  amount: !sum '1.23 EUR'
  name: discount a
- !discount
  amount: !sum '20.45 EUR'
  name: discount β
items:
- !item
  name: item a
  price_brutto: !sum '1.23 EUR'
- !item
  name: item β
  price_brutto: !sum '20.45 EUR'
order_date: 2016-05-08
order_id: id
platform: platformπ
""")
    order_expected = get_order_a()
    assert order_expected == order_loaded, yaml_diff(order_expected, order_loaded)

def test_scalar_figure_to_yaml():
    assert to_yaml(dingguo.ScalarFigure(1.34, u'μm')) == u"!scalar '1.34 μm'\n"

def test_scalar_figure_from_yaml():
    assert dingguo.ScalarFigure(1.34, u'μm') == yaml.load(u"!scalar '1.34 μm'")

def test_distance_to_yaml():
    assert to_yaml(dingguo.Distance(1.34, u'km')) == u"!distance '1.34 km'\n"

def test_distance_from_yaml():
    assert dingguo.Distance(1.34, u'km') == yaml.load(u"!distance '1.34 km'\n")

def test_article_to_yaml():
    assert to_yaml(get_article()) == u"""!article
authors:
- a
- b
delivery_date: null
depth: !scalar '12.3 dm'
features: supergeil
height: !scalar '123.0 cm'
maximum_load: !scalar '40.0 kg'
name: article name
price_brutto: !sum '1.23 EUR'
product_id: 0815
quantity: 1
reseller: seller
shipper: shipper
state: goood
width: !scalar '1.23 m'
"""

def test_article_from_yaml():
    assert get_article() == yaml.load(u"""!article
authors:
- a
- b
delivery_date: null
features: supergeil
name: article name
price_brutto: !sum '1.23 EUR'
product_id: 0815
quantity: 1
reseller: seller
shipper: shipper
state: goood
depth: !scalar 12.3 dm
height: !scalar 123.0 cm
maximum_load: !scalar 40.0 kg
width: !scalar 1.23 m
""")

def test_transportation_to_yaml():
    assert to_yaml(get_transportation()) == u"""!transportation
departure_point: home
destination_point: city
distance: !distance '3.21 km'
name: ticket
price_brutto: !sum '1.23 EUR'
route_map: null
"""

def test_transportation_from_yaml():
    assert get_transportation() == yaml.load(u"""!transportation
departure_point: home
destination_point: city
distance: !distance '3.21 km'
name: ticket
price_brutto: !sum '1.23 EUR'
route_map: null
""")

def test_taxi_ride_to_yaml():
    assert to_yaml(get_taxi_ride()) == u"""!taxi-ride
arrival_time: 2016-05-02 18:10:00
departure_point: home
departure_time: 2016-05-02 18:25:00
destination_point: city
distance: !distance '3.21 km'
driver: driver
name: taxi ride
price_brutto: !sum '1.23 EUR'
route_map: null
"""

def test_taxi_ride_from_yaml():
    assert get_taxi_ride() == yaml.load(u"""!taxi-ride
arrival_time: 2016-05-02 18:10:00
departure_point: home
departure_time: 2016-05-02 18:25:00
destination_point: city
distance: !distance '3.21 km'
driver: driver
name: taxi ride
price_brutto: !sum '1.23 EUR'
route_map: null
""")

def test_order_registry_to_yaml():
    assert to_yaml(get_order_registry()) == u"""!order-registry
platformπ:
  id: !order
    customer_id: customer
    discounts: []
    items: []
    order_date: 2016-05-08
    order_id: id
    platform: platformπ
  order_b: !order
    customer_id: null
    discounts: []
    items: []
    order_date: 2015-05-08
    order_id: order_b
    platform: platformπ
γάμμα:
  order_βήτα: !order
    customer_id: ρώ
    discounts: []
    items: []
    order_date: 2014-05-08
    order_id: order_βήτα
    platform: γάμμα
"""

def test_order_registry_from_yaml():
    expected = get_order_registry()
    loaded = yaml.load(u"""!order-registry
platformπ:
  id: !order
    customer_id: customer
    discounts: []
    order_date: 2016-05-08
    order_id: id
    platform: platformπ
  order_b: !order
    customer_id: null
    items: []
    order_date: 2015-05-08
    order_id: order_b
    platform: platformπ
γάμμα:
  order_βήτα: !order
    customer_id: ρώ
    discounts: []
    items: []
    order_date: 2014-05-08
    order_id: order_βήτα
    platform: γάμμα
""")
    assert expected == loaded, yaml_diff(expected, loaded)