package com.dynamicwallpaper.gui;

import com.dynamicwallpaper.model.WallpaperImage;
import com.dynamicwallpaper.util.ThumbnailLoader;

import javax.swing.Icon;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/** Backs the solar-mode table: one row per image, with editable altitude/azimuth/reference columns. */
final class SolarImageTableModel extends AbstractTableModel {

    private static final String[] COLUMNS = {
            "Preview", "File", "Altitude (°)", "Azimuth (°)", "Light Ref.", "Dark Ref."
    };

    private final List<WallpaperImage> images = new ArrayList<>();

    List<WallpaperImage> images() {
        return Collections.unmodifiableList(images);
    }

    void add(WallpaperImage image) {
        images.add(image);
        int row = images.size() - 1;
        fireTableRowsInserted(row, row);
    }

    void removeRows(int[] rows) {
        List<WallpaperImage> toRemove = new ArrayList<>();
        for (int row : rows) {
            toRemove.add(images.get(row));
        }
        images.removeAll(toRemove);
        fireTableDataChanged();
    }

    void clear() {
        images.clear();
        fireTableDataChanged();
    }

    void moveRow(int from, int to) {
        if (to < 0 || to >= images.size()) {
            return;
        }
        WallpaperImage moved = images.remove(from);
        images.add(to, moved);
        fireTableDataChanged();
    }

    @Override
    public int getRowCount() {
        return images.size();
    }

    @Override
    public int getColumnCount() {
        return COLUMNS.length;
    }

    @Override
    public String getColumnName(int column) {
        return COLUMNS[column];
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return switch (columnIndex) {
            case 0 -> Icon.class;
            case 1 -> String.class;
            case 2, 3 -> Double.class;
            case 4, 5 -> Boolean.class;
            default -> Object.class;
        };
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex >= 2;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        WallpaperImage image = images.get(rowIndex);
        return switch (columnIndex) {
            case 0 -> ThumbnailLoader.thumbnail(image.file(), 40);
            case 1 -> image.name();
            case 2 -> image.altitude();
            case 3 -> image.azimuth();
            case 4 -> image.isLightReference();
            case 5 -> image.isDarkReference();
            default -> null;
        };
    }

    @Override
    public void setValueAt(Object value, int rowIndex, int columnIndex) {
        WallpaperImage image = images.get(rowIndex);
        switch (columnIndex) {
            case 2 -> image.setAltitude(((Number) value).doubleValue());
            case 3 -> image.setAzimuth(((Number) value).doubleValue());
            case 4 -> setExclusiveFlag(rowIndex, (Boolean) value, true);
            case 5 -> setExclusiveFlag(rowIndex, (Boolean) value, false);
            default -> {
                return;
            }
        }
        fireTableRowsUpdated(rowIndex, rowIndex);
    }

    /** Only one row at a time may be the light reference, and separately only one may be the dark reference. */
    private void setExclusiveFlag(int rowIndex, boolean value, boolean light) {
        for (int i = 0; i < images.size(); i++) {
            WallpaperImage image = images.get(i);
            boolean newValue = (i == rowIndex) && value;
            if (light) {
                image.setLightReference(newValue);
            } else {
                image.setDarkReference(newValue);
            }
        }
        fireTableDataChanged();
    }
}
