import java.util.*;
import java.text.NumberFormat;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class NumberFormatDemo extends Application {
  // Pole kombi do wybierania dostępnych ustawień regionalnych
  private ComboBox<String> cboLocale = new ComboBox<>();

  // Pola tekstowe ze stopą oprocentowania, latami spłaty i kwotą kredytu
  private TextField tfInterestRate = new TextField("6.75");
  private TextField tfNumberOfYears = new TextField("15");
  private TextField tfLoanAmount = new TextField("107000");
  private TextField tfFormattedInterestRate = new TextField();
  private TextField tfFormattedNumberOfYears = new TextField();
  private TextField tfFormattedLoanAmount = new TextField();

  // Pola tekstowe z miesięczną ratą i łączną kwotą do spłaty
  private TextField tfTotalPayment = new TextField();
  private TextField tfMonthlyPayment = new TextField();

  // Przycisk Oblicz
  private Button btCompute = new Button("Oblicz");

  // Aktualne ustawienia regionalne
  private Locale locale = Locale.getDefault();

  // Deklaracja tablicy locales do przechowywania dostępnych ustawień regionalnych
  private Locale locales[] = Calendar.getAvailableLocales();

  /** Inicjowanie pola kombi */
  public void initializeComboBox() {
    // Dodawanie nazw ustawień regionalnych do pola kombi
    for (int i = 0; i < locales.length; i++)
      cboLocale.getItems().add(locales[i].getDisplayName());
  }

  @Override // Przesłanianie metody start z klasy Application
  public void start(Stage primaryStage) {
    initializeComboBox();
    
    // Panel zawierający pole kombi do wybierania ustawień regionalnych
    HBox hBox = new HBox(5);
    hBox.getChildren().addAll(
      new Label("Wybierz ustawienia regionalne"), cboLocale);

    // Panel na dane wejściowe
    GridPane gridPane = new GridPane();
    gridPane.add(new Label("Stopa oprocentowania"), 0, 0);
    gridPane.add(tfInterestRate, 1, 0);
    gridPane.add(tfFormattedInterestRate, 2, 0);
    gridPane.add(new Label("Liczba lat"), 0, 1);
    gridPane.add(tfNumberOfYears, 1, 1);
    gridPane.add(tfFormattedNumberOfYears, 2, 1);
    gridPane.add(new Label("Kwota kredytu"), 0, 2);
    gridPane.add(tfLoanAmount, 1, 2);
    gridPane.add(tfFormattedLoanAmount, 2, 2);

    // Panel na dane wyjściowe 
    GridPane gridPaneOutput = new GridPane();
    gridPaneOutput.add(new Label("Miesięczna rata"), 0, 0);
    gridPaneOutput.add(tfMonthlyPayment, 1, 0);
    gridPaneOutput.add(new Label("Kwota do spłaty"), 0, 1);
    gridPaneOutput.add(tfTotalPayment, 1, 1);

    // Wyrównywanie pól tekstowych
    tfFormattedInterestRate.setAlignment(Pos.BASELINE_RIGHT);
    tfFormattedNumberOfYears.setAlignment(Pos.BASELINE_RIGHT);
    tfFormattedLoanAmount.setAlignment(Pos.BASELINE_RIGHT);
    tfTotalPayment.setAlignment(Pos.BASELINE_RIGHT);
    tfMonthlyPayment.setAlignment(Pos.BASELINE_RIGHT);

    // Blokowanie możliwości edycji
    tfFormattedInterestRate.setEditable(false);
    tfFormattedNumberOfYears.setEditable(false);
    tfFormattedLoanAmount.setEditable(false);
    tfTotalPayment.setEditable(false);
    tfMonthlyPayment.setEditable(false);

    VBox vBox = new VBox(5);
    vBox.getChildren().addAll(hBox, 
       new Label("Wpisz roczne oprocentowanie, " +
         "liczbę lat spłaty i kwotę kredytu"), gridPane,
       new Label("Do spłaty"), gridPaneOutput, btCompute);

    // Tworzenie sceny i umieszczanie jej w oknie
    Scene scene = new Scene(vBox, 400, 300);
    primaryStage.setTitle("NumberFormatDemo"); // Ustawianie nagłówka
    primaryStage.setScene(scene); // Umieszczanie sceny w oknie
    primaryStage.show(); // Wyświetlanie okna

    // Rejestrowanie odbiorników
    cboLocale.setOnAction(e -> {
      locale = locales[cboLocale
        .getSelectionModel().getSelectedIndex()];
      computeLoan();
    });

    btCompute.setOnAction(e -> computeLoan());
  }

  /** Obliczanie rat i wyświetlanie wyników zgodnie z ustawieniami regionalnymi */
  private void computeLoan() {
    // Pobieranie danych wejściowych od użytkownika
    double loan = new Double(tfLoanAmount.getText()).doubleValue();
    double interestRate =
      new Double(tfInterestRate.getText()).doubleValue() / 1240;
    int numberOfYears =
      new Integer(tfNumberOfYears.getText()).intValue();

    // Obliczanie rat
    double monthlyPayment = loan * interestRate/
     (1 - (Math.pow(1 / (1 + interestRate), numberOfYears * 12)));
    double totalPayment = monthlyPayment * numberOfYears * 12;

    // Pobieranie obiektów formatujących
    NumberFormat percentFormatter =
      NumberFormat.getPercentInstance(locale);
    NumberFormat currencyForm =
      NumberFormat.getCurrencyInstance(locale);
    NumberFormat numberForm = NumberFormat.getNumberInstance(locale);
    percentFormatter.setMinimumFractionDigits(2);

    // Wyświetlanie sformatowanych danych wejściowych
    tfFormattedInterestRate.setText(
      percentFormatter.format(interestRate * 12));
    tfFormattedNumberOfYears.setText
      (numberForm.format(numberOfYears));
    tfFormattedLoanAmount.setText(currencyForm.format(loan));

    // Wyświetlanie wyników jako wartości pieniężnych
    tfMonthlyPayment.setText(currencyForm.format(monthlyPayment));
    tfTotalPayment.setText(currencyForm.format(totalPayment));
  }

  /**
   * Metoda main jest potrzebna tylko w środowiskach IDE z ograniczoną obsługą platformy JavaFX.
   * Nie jest potrzebna przy uruchamianiu kodu w wierszu poleceń.
   */
  public static void main(String[] args) {
    launch(args);
  }
}