/*
 * Copyright (C) 2025 ctecinf.com.br
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.com.ctecinf.jetty;

import java.awt.Component;
import java.awt.Dimension;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;

/**
 *
 * @author Cássio Conceição
 * @since 07/03/2025
 * @version 2503
 * @see http://hobbyslotcar.com.br
 */
public abstract class Config {

    private final LinkedHashMap<String, String> props = new LinkedHashMap();
    private final File file = new File("config", getFileName() + ".properties");

    public abstract String getFileName();

    public Config() {
        try {
            load();
        } catch (JettyException ex) {
            JOptionPane.showMessageDialog(null, ex, "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    public final void store() throws JettyException {
        if (!file.exists()) {
            file.getParentFile().mkdirs();
        }
        try (FileOutputStream out = new FileOutputStream(file)) {
            out.write(String.valueOf("#Config file of " + getFileName() + "\n").getBytes());
            for (Map.Entry<String, String> entry : props.entrySet()) {
                out.write(String.valueOf(entry.getKey() + "=" + entry.getValue() + "\n").getBytes());
            }
        } catch (IOException ex) {
            throw new JettyException(ex);
        }
    }

    public final void load() throws JettyException {
        if (!file.exists()) {
            store();
        }
        props.clear();
        try {
            for (String line : new String(Files.readAllBytes(file.toPath())).split("\n")) {
                int pos = line.indexOf("=");
                if (!line.trim().startsWith("#") && pos > -1) {
                    props.put(line.substring(0, pos).trim(), line.substring(pos + 1).trim());
                }
            }
        } catch (IOException ex) {
            throw new JettyException(ex);
        }
    }

    public final void clear() throws JettyException {
        props.clear();
        store();
    }

    public final boolean isEmpty() {
        return props.isEmpty();
    }

    public final Set<String> keySet() {
        return props.keySet();
    }

    public final Collection<String> values() {
        return props.values();
    }

    public final void add(String name, Object value) throws JettyException {
        props.put(name, String.valueOf(value));
        store();
    }

    public final void remove(String name) throws JettyException {
        props.remove(name);
        store();
    }

    public final File getFile() {
        return file;
    }

    public final <T extends ConfigObject> JList<T> getList(Class<T> model) {
        JList<T> list = new JList(new DefaultListModel());
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setPreferredSize(new Dimension(300, 0));
        list.setCellRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                setBorder(BorderFactory.createEmptyBorder());
                return this;
            }
        });
        for (String name : keySet()) {
            try {
                T obj = model.getConstructor().newInstance();
                obj.setName(name);
                ((DefaultListModel<T>) list.getModel()).addElement(obj);
            } catch (IllegalAccessException | IllegalArgumentException | InstantiationException | NoSuchMethodException | SecurityException | InvocationTargetException ex) {
                System.err.println(ex);
            }
        }
        return list;
    }

    public interface ConfigObject {

        public String getName();

        public void setName(String name);
    }
}
