package fi.lpam.gui;

import fi.lpam.dataluokat.Asiakas;
import fi.lpam.dataluokat.Kierros;
import fi.lpam.dataluokat.Kuljetus;
import fi.lpam.tulostajat.KuljetusListaTulostaja;
import fi.lpam.gui.elementit.MaaraTableColumn;
import fi.lpam.gui.elementit.TabPohja;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.ChoiceBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Objects;


@SuppressWarnings("unchecked")
public class KuljetusListat extends TabPohja {
    private final TableView<Kuljetus> tableView = new TableView<>();
    private final DatePicker datePicker = new DatePicker(LocalDate.now());
    private final ComboBox<Integer> kierrosValinta = new ComboBox<>(FXCollections.observableArrayList(Kierros.haeKierrosNumerot()));
    private final Label tallennusStatus;
    private final Button btnTulosta;

    public KuljetusListat() {
        ObservableList<Integer> määräVaihtoehdot = FXCollections.observableArrayList();
        for (int i = 0; i <= 10; i++) {
            määräVaihtoehdot.add(i);}

        BorderPane root = new BorderPane();
        root.setPadding(oletusInsets);
        this.getChildren().add(root);

        BorderPane yläpalkki =  new BorderPane();
        Label infoTeksti = new Label("Kuljetuslistojen luonti");
        infoTeksti.setFont(tekstiFont);
        yläpalkki.setLeft(infoTeksti);

        HBox kierroksenValintaLaatikko = new HBox();
        kierroksenValintaLaatikko.setSpacing(5);
        kierroksenValintaLaatikko.setSpacing(5);
        kierroksenValintaLaatikko.setAlignment(Pos.CENTER);
        Button valitse = new Button("Valitse");
        valitse.setFont(buttonFont);
        valitse.setOnAction(_ -> päivitäListanäkymä());
        tallennusStatus = new Label("Tallennettu: Kyllä");
        tallennusStatus.setFont(tekstiFont);
        datePicker.valueProperty().addListener(_ -> päivitäListanäkymä());
        kierrosValinta.valueProperty().addListener(_ -> päivitäListanäkymä());
        kierroksenValintaLaatikko.getChildren().addAll(
                new Label("Valitse päivämäärä:"),
                datePicker,
                new Label("Valitse kierros:"),
                kierrosValinta, tallennusStatus);
        yläpalkki.setCenter(kierroksenValintaLaatikko);

        HBox napit = new HBox();
        napit.setSpacing(5);
        Button poista = new Button("Poista kuljetusrivi");
        poista.setOnAction(_ ->poistaRivi());
        poista.setFont(buttonFont);
        Button tallenna = new Button("Tallenna");
        tallenna.setFont(buttonFont);
        tallenna.setOnAction(_ -> tallennaKierros());
        btnTulosta = new Button("Tulosta lista");
        btnTulosta.setDisable(true);
        btnTulosta.setFont(buttonFont);
        btnTulosta.setOnAction(_ ->tulostaLista());
        napit.getChildren().addAll(poista, tallenna, btnTulosta);
        yläpalkki.setRight(napit);
        root.setTop(yläpalkki);

        tableView.setEditable(true);
        tableView.setPlaceholder(new Label("Valitse kierros aloittaaksesi"));
        root.setCenter(tableView);

        TableColumn<Kuljetus, String> tcNimi =  new TableColumn<>("Nimi");
        tcNimi.setMinWidth(150);
        tcNimi.setCellFactory(TextFieldTableCell.forTableColumn());
        tcNimi.setCellValueFactory(new PropertyValueFactory<>("nimi"));
        tcNimi.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, String> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setNimi(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        TableColumn<Kuljetus, String> tcOsoite =  new TableColumn<>("Osoite");
        tcOsoite.setMinWidth(250);
        tcOsoite.setCellFactory(TextFieldTableCell.forTableColumn());
        tcOsoite.setCellValueFactory(new PropertyValueFactory<>("osoite"));
        tcOsoite.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, String> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setOsoite(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        TableColumn<Kuljetus, Integer> tcSalaatit = new MaaraTableColumn<>("Salaatit", 100);
        tcSalaatit.setCellFactory(ChoiceBoxTableCell.forTableColumn(määräVaihtoehdot));
        tcSalaatit.setCellValueFactory(new PropertyValueFactory<>("salaatit"));
        tcSalaatit.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, Integer> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setSalaatit(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        TableColumn<Kuljetus, Integer> tcPääruoat = new MaaraTableColumn<>("Pääruoat", 100);
        tcPääruoat.setCellFactory(ChoiceBoxTableCell.forTableColumn(määräVaihtoehdot));
        tcPääruoat.setCellValueFactory(new PropertyValueFactory<>("pääruoat"));
        tcPääruoat.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, Integer> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setPääruoat(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        TableColumn<Kuljetus, Integer> tcJälkiruoat = new MaaraTableColumn<>("Jälkiruoat", 100);
        tcJälkiruoat.setCellFactory(ChoiceBoxTableCell.forTableColumn(määräVaihtoehdot));
        tcJälkiruoat.setCellValueFactory(new PropertyValueFactory<>("jälkiruoat"));
        tcJälkiruoat.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, Integer> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setJälkiruoat(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        TableColumn<Kuljetus, String> tcRuokarajoite = new TableColumn<>("Ruokarajoite");
        tcRuokarajoite.setMinWidth(200);
        tcRuokarajoite.setCellFactory(TextFieldTableCell.forTableColumn());
        tcRuokarajoite.setCellValueFactory(new PropertyValueFactory<>("ruokarajoite"));
        tcRuokarajoite.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, String> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setRuokarajoite(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        TableColumn<Kuljetus, String> tcLisätieto = new TableColumn<>("Lisätieto kuljetukselle");
        tcLisätieto.setMinWidth(200);
        tcLisätieto.setCellFactory(TextFieldTableCell.forTableColumn());
        tcLisätieto.setCellValueFactory(new PropertyValueFactory<>("lisätieto"));
        tcLisätieto.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, String> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setLisätieto(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        TableColumn<Kuljetus, String> tcAvainTieto = new TableColumn<>("Avaintieto");
        tcAvainTieto.setMinWidth(200);
        tcAvainTieto.setCellFactory(TextFieldTableCell.forTableColumn());
        tcAvainTieto.setCellValueFactory(new PropertyValueFactory<>("avainTieto"));
        tcAvainTieto.setOnEditCommit((TableColumn.CellEditEvent<Kuljetus, String> event) -> {event.getTableView().getItems().get(event.getTablePosition().getRow()).setAvainTieto(event.getNewValue()); tallennusStatus.setText("Tallennettu: Ei");});

        tableView.getColumns().addAll(tcNimi, tcOsoite, tcSalaatit, tcPääruoat, tcJälkiruoat, tcRuokarajoite, tcLisätieto, tcAvainTieto);

        for (TableColumn<Kuljetus, ?> sarake : tableView.getColumns()) {
            sarake.setSortable(false);
            sarake.setEditable(true);
            sarake.setResizable(true);
            sarake.setStyle("-fx-alignment: CENTER; -fx-font-size: 16px;");
        }
    }

    private void päivitäListanäkymä() {
        LocalDate valittuPäivä = datePicker.getValue();
        int valittuKierros = kierrosValinta.getValue();

        ArrayList<Kuljetus> luetutKuljetuksetKierrokselle = Kuljetus.haePäivänKuljetuksetKierroksella(valittuPäivä, valittuKierros);
        ObservableList<Asiakas> kierroksenAsiakkaat = Objects.requireNonNull(Kierros.haeKierros(valittuKierros)).getAsiakkaat();
        ArrayList<Kuljetus> näytettävätKuljetukset = new ArrayList<>();
        HashSet<Integer> näytettävätAsiakasIDt = new HashSet<>();
        //Luodaan kierroksen kuljetusdata kierrosjärjestyksen mukaan
        for (Asiakas asiakas : kierroksenAsiakkaat) {
            näytettävätKuljetukset.add(new Kuljetus(asiakas, valittuPäivä, valittuKierros));
            näytettävätAsiakasIDt.add(asiakas.getId());
        }
        //Yhdistetään tietokannan data järjestys säilyttäen
        for (Kuljetus luettuKuljetus : Objects.requireNonNull(luetutKuljetuksetKierrokselle)) {
            if (näytettävätAsiakasIDt.contains(luettuKuljetus.getAsiakasID())) {
                for (Kuljetus näytettäväKuljetus : näytettävätKuljetukset) {
                    if (näytettäväKuljetus.getAsiakasID() == luettuKuljetus.getAsiakasID()) {
                        näytettävätKuljetukset.set(näytettävätKuljetukset.indexOf(näytettäväKuljetus), luettuKuljetus);
                    }
                }
            }
            else {
                näytettävätKuljetukset.add(luettuKuljetus);
            }
        }

        tableView.setItems(FXCollections.observableArrayList(näytettävätKuljetukset));
        tallennusStatus.setText("Tallennettu: Ei");
        btnTulosta.setDisable(true);
    }

    private void poistaRivi() {
        Kuljetus valittu = tableView.getSelectionModel().getSelectedItem();
        tableView.getItems().remove(valittu);
        if (valittu.getId() > 0) {valittu.poista();}
        tableView.refresh();
        tallennusStatus.setText("Tallennettu: Ei");
    }

    private void tallennaKierros() {
        try {
            for (Kuljetus kuljetus : tableView.getItems()) {
                if (kuljetus.getId() > 0) {
                    kuljetus.päivitäTietokantaan();
                } else {
                    kuljetus.tallennaUusi();
                }
            }
            tallennusStatus.setText("Tallennettu: Kyllä");
            btnTulosta.setDisable(false);
        }
        catch (Exception e) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("Virhe");
            alert.setHeaderText("Tallennus epäonnistui");
            alert.setContentText(e.getMessage());
            alert.showAndWait();
        }
    }

    private void tulostaLista() {
        KuljetusListaTulostaja.tulosta(tableView.getItems(), kierrosValinta.getValue());
    }
}