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

"""
SPDX-FileCopyrightText: Patrik Schönfeldt
SPDX-FileCopyrightText: Daniel Niederhöfer
SPDX-FileCopyrightText: DLR e.V.

SPDX-License-Identifier: MIT
"""

# %%[imports]
import os

import matplotlib.pyplot as plt
import networkx as nx
import numpy as np
import pandas as pd

from oemof import solph

# %%[input_data]

file_path = os.path.dirname(__file__)
filename = os.path.join(file_path, "pv_example_data.csv")
input_data = pd.read_csv(
    filename, index_col="timestep", parse_dates=["timestep"]
)

# %%[energy_system]

energy_system = solph.EnergySystem(
    timeindex=input_data.index,
    infer_last_interval=True,
)

# %%[dispatch_model]

ac_bus = solph.Bus(label="electricity")

demand = solph.components.Sink(
    label="demand",
    inputs={
        ac_bus: solph.Flow(
            nominal_capacity=1,
            fix=input_data["electricity demand (kW)"],
        )
    },
)

energy_system.add(ac_bus, demand)

grid = solph.Bus(
    label="grid",
    inputs={ac_bus: solph.Flow(variable_costs=-0.06)},
    outputs={ac_bus: solph.Flow(variable_costs=0.3)},
    balanced=False,
)

energy_system.add(grid)

# %%[pv_system]
dc_bus = solph.Bus(label="DC")

pv_specific_costs = 1200  # €/kW
pv_lifetime = 20  # years
pv_epc = pv_specific_costs / pv_lifetime

pv_panels = solph.components.Source(
    label="PV",
    outputs={
        dc_bus: solph.Flow(
            nominal_capacity=solph.Investment(ep_costs=pv_epc, maximum=10),
            maximum=input_data["pv yield (kW/kW)"] / 0.95,
        )
    },
)

inverter_specific_costs = 300  # €/kW
inverter_lifetime = 20  # years
inverter_epc = inverter_specific_costs / inverter_lifetime

inverter = solph.components.Converter(
    label="inverter",
    inputs={
        dc_bus: solph.Flow(
            nominal_capacity=solph.Investment(ep_costs=inverter_epc)
        )
    },
    outputs={ac_bus: solph.Flow()},
    conversion_factors={ac_bus: 0.95},
)

energy_system.add(dc_bus, pv_panels, inverter)

# %%[battery]
battery_specific_costs = 750  # €/kW
battery_lifetime = 20  # years
battery_epc = battery_specific_costs / battery_lifetime
battery_size = solph.Investment(ep_costs=battery_epc)

battery = solph.components.GenericStorage(
    label="Battery",
    nominal_capacity=battery_size,
    inputs={ac_bus: solph.Flow()},
    outputs={ac_bus: solph.Flow()},
    inflow_conversion_factor=0.9,
    loss_rate=0.01,
)

energy_system.add(battery)

# %%[graph_plotting]
plt.figure()
graph = energy_system.to_networkx()
nx.draw(graph, with_labels=True, font_size=8)
# %%[model_optimisation]
model = solph.Model(energy_system)

results = model.solve(solver="cbc", solve_kwargs={"tee": True})

# %%[results]

# Potentially, there are more points in time to invest.
# For upfront invest, we need to select the initial.
pv_size = results["invest"][(pv_panels, dc_bus)][0]
pv_annuity = pv_epc * pv_size

inverter_size = results["invest"][(dc_bus, inverter)][0]
inverter_annuity = inverter_epc * inverter_size

battery_size = results["invest"][battery][0]
battery_annuity = battery_epc * battery_size

annual_grid_supply = results["flow"][(grid, ac_bus)].sum()
el_costs = 0.3 * annual_grid_supply
el_revenue = 0.1 * results["flow"][(ac_bus, grid)].sum()

tce = results["objective"]

print(f"The optimal PV size is {pv_size:.2f} kW.")
print(f"The optimal inverter size is {inverter_size:.2f} kW.")
print(f"The optimal battery size is {battery_size:.2f} kWh.")

print(f"The annual costs for grid electricity are {el_costs:.2f} €.")
print(f"The annual revenue from feed-in is {el_revenue:.2f} €.")
print(f"The annuity for the PV system is {pv_annuity:.2f} €.")
print(f"The annuity for the battery is {battery_annuity:.2f} €.")
print(f"The total annual costs are {tce:.2f} €.")

annual_demand = input_data["electricity demand (kW)"].sum()

print(
    f"Autarky is 1 - {annual_grid_supply:.2f} kWh / {annual_demand:.2f} kWh"
    + f" = {100 - 100 * annual_grid_supply / annual_demand:.2f} %."
)

flows = results["flow"]

baseline = np.zeros(len(flows))

plt.figure()

mode = "light"
# mode = "dark"
if mode == "dark":
    plt.style.use("dark_background")

plt.fill_between(
    flows.index,
    baseline,
    baseline + flows[("grid", "electricity")],
    step="pre",
    label="Grid supply",
)

baseline += flows[("grid", "electricity")]

plt.fill_between(
    flows.index,
    baseline,
    baseline + flows[("inverter", "electricity")],
    step="pre",
    label="PV supply",
)

baseline += flows[("inverter", "electricity")]

plt.fill_between(
    flows.index,
    baseline,
    baseline + flows[("Battery", "electricity")],
    step="pre",
    label="Battery supply",
)

plt.step(
    flows.index,
    flows[("electricity", "demand")],
    "-",
    color="darkgrey",
    label="Electricity demand",
)

plt.step(
    flows.index,
    flows[("electricity", "demand")] + flows[("electricity", "Battery")],
    "--",
    color="darkgrey",
    label="Battery charging",
)

plt.step(
    flows.index,
    flows[("electricity", "demand")]
    + flows[("electricity", "Battery")]
    + flows[("electricity", "grid")],
    ":",
    color="darkgrey",
    label="Feed-In",
)

plt.legend()
plt.ylabel("Power (kW)")
plt.xlim(pd.Timestamp("2020-02-21 00:00"), pd.Timestamp("2020-02-28 00:00"))
plt.gcf().autofmt_xdate()

plt.savefig(f"home_pv_result-5_{mode}.svg")

plt.show()
