import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.text.TextAlignment;

public class CalendarPane extends BorderPane {
  // Nagłówek
  private Label lblHeader = new Label();

  // Maksymalna liczba etykiet do wyświetlania nazw i numerów dni
  private Label[] lblDay = new Label[49];

  private Calendar calendar;
  private int month;  // Miesiąc
  private int year;  // Rok
  private Locale locale = Locale.CHINA;

  public CalendarPane() {
	// Tworzenie etykiet do wyświetlania dni
    for (int i = 0; i < 49; i++) {
      lblDay[i] = new Label();
      lblDay[i].setTextAlignment(TextAlignment.RIGHT);
    }

    showDayNames(); // Wyświetlanie nazw dni zgodnie z ustawieniami regionalnymi

    GridPane dayPane = new GridPane();
    dayPane.setAlignment(Pos.CENTER);

    dayPane.setHgap(10);
    dayPane.setVgap(10);
    for (int i = 0; i < 49; i++) {
      dayPane.add(lblDay[i], i % 7, i / 7);
    }

	// Umieszczanie nagłówka i głównej zawartości kalendarza w panelu
    this.setTop(lblHeader);
    BorderPane.setAlignment(lblHeader, Pos.CENTER);
    this.setCenter(dayPane);

	// Ustawianie bieżącego miesiąca i roku
    calendar = new GregorianCalendar();
    month = calendar.get(Calendar.MONTH);
    year = calendar.get(Calendar.YEAR);
    updateCalendar();

    // Wyświetlanie kalendarza
    showHeader();
    showDays();
  }
  
  /** Aktualizowanie nazw dni zgodnie z ustawieniami regionalnymi */
  private void showDayNames() {
    DateFormatSymbols dfs = new DateFormatSymbols(locale);
    String dayNames[] = dfs.getWeekdays();

	// jlblDay[0], jlblDay[1], …, jlblDay[6] zawierają nazwy dni
    for (int i = 0; i < 7; i++) {
      lblDay[i].setText(dayNames[i + 1]);
    }
  }
  
  /** Aktualizowanie nagłówka zgodnie z ustawieniami regionalnymi */
  private void showHeader() {
    SimpleDateFormat sdf =
      new SimpleDateFormat("MMMM yyyy", locale);
    String header = sdf.format(calendar.getTime());
    lblHeader.setText(header);
  }

  public void showDays() {
	// Pobieranie dnia tygodnia przypadającego pierwszego dnia miesiąca
    int startingDayOfMonth = calendar.get(Calendar.DAY_OF_WEEK);

	// Zapełnianie kalendarza dniami poprzedzającymi bieżący miesiąc
    Calendar cloneCalendar = (Calendar) calendar.clone();
    cloneCalendar.add(Calendar.DATE, -1); // Uwzględnianie poprzedniego miesiąca
    int daysInPrecedingMonth = cloneCalendar.getActualMaximum(
      Calendar.DAY_OF_MONTH);

    for (int i = 0; i < startingDayOfMonth - 1; i++) {
      lblDay[i + 7].setTextFill(Color.LIGHTGRAY);
      lblDay[i + 7].setText(daysInPrecedingMonth
        - startingDayOfMonth + 2 + i + "");
    }

	// Wyświetlanie dni z bieżącego miesiąca
    int daysInCurrentMonth = calendar.getActualMaximum(
      Calendar.DAY_OF_MONTH);
    for (int i = 1; i <= daysInCurrentMonth; i++) {
      lblDay[i - 2 + startingDayOfMonth + 7].setTextFill(Color.BLACK);
      lblDay[i - 2 + startingDayOfMonth + 7].setText(i + "");
    }

  	// Zapełnianie kalendarza dniami następnego miesiąca
    int j = 1;
    for (int i = daysInCurrentMonth - 1 + startingDayOfMonth + 7;
         i < 49; i++) {
      lblDay[i].setTextFill(Color.LIGHTGRAY);
      lblDay[i].setText(j++ + "");
    }
  }

  /** Ustawianie kalendarza na pierwszy dzień
    * podanego miesiąca określonego roku
   */
  public void updateCalendar() {
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, month);
    calendar.set(Calendar.DATE, 1);
  }

  public int getMonth() {
    return month;
  }

  public void setMonth(int newMonth) {
    month = newMonth;
    updateCalendar();
    showHeader();
    showDays();
  }

  public int getYear() {
    return year;
  }

  public void setYear(int newYear) {
    year = newYear;
    updateCalendar();
    showHeader();
    showDays();
  }
  
  public void setLocale(Locale locale) {
    this.locale = locale;
    updateCalendar();
    showDayNames();
    showHeader();
    showDays();
  }
}
