// Copyright 2014-2025 Jesper Larsson
//
// This file is part of Klipspringer, <https://klipspringer.avadeaux.net/>
//
// Klipspringer 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.
//
// Klipspringer 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 Klipspringer. If
// not, see <https://www.gnu.org/licenses/>.

package net.avadeaux.klipspringer;

import java.net.URLDecoder;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class Query {
    public enum Onoff { ON, OFF, DETECT }

    final Map<String, String> q;

    private Query(Map<String, String> q) { this.q = q; }

    public static Onoff toggle(Onoff v) {
        switch (v) {
        case ON: return Onoff.OFF;
        case OFF: return Onoff.ON;
        default: return v;
        }
    }

    public String value(String name, String fall) {
        String v = q.get(name);
        return v == null ? fall : v;
    }

    public int intValue(String name, int fall) {
        String v = q.get(name);
        if (v != null) {
            try { return Integer.parseInt(v); } catch (NumberFormatException ex) {
                if (System.getProperty("klipspringer.debug") != null) { ex.printStackTrace(); }
            }
        }
        return fall;
    }

    public long longValue(String name, long fall) {
        String v = q.get(name);
        if (v != null) {
            try { return Long.parseLong(v); } catch (NumberFormatException ex) {
                if (System.getProperty("klipspringer.debug") != null) { ex.printStackTrace(); }
            }
        }
        return fall;
    }

    public double doubleValue(String name, double fall) {
        String v = q.get(name);
        if (v != null) {
            try {
                double d = Double.parseDouble(v);
                if (!Double.isNaN(d)) { return d; }
            } catch (NumberFormatException ex) {
                if (System.getProperty("klipspringer.debug") != null) { ex.printStackTrace(); }
            }
        }
        return fall;
    }

    public boolean booleanValue(String name, boolean fall) {
        String v = q.get(name);
        if (v != null) {
            try { return Boolean.parseBoolean(v); } catch (NumberFormatException ex) {
                if (System.getProperty("klipspringer.debug") != null) { ex.printStackTrace(); }
            }
        }
        return fall;
    }

    public Onoff onoffValue(String name) { return onoffValue(name, Onoff.DETECT); }

    public Onoff onoffValue(String name, Onoff fall) {
        String v = q.get(name);
        if (v != null) {
            try { return Onoff.valueOf(v.toUpperCase()); } catch (IllegalArgumentException ex) {
                if (System.getProperty("klipspringer.debug") != null) { ex.printStackTrace(); }
            }
        }
        return fall;
    }

    public static Query parse(String s) {
        Map<String, String> q = new HashMap<String, String>();
        String[] args = s.split("&");
        for (String arg : args) {
            int p = arg.indexOf("=");
            if (p < 0) {
                q.put(arg, "");
            } else {
                try {
                    q.put(arg.substring(0, p), URLDecoder.decode(arg.substring(p+1), StandardCharsets.UTF_8.name()));
                } catch (UnsupportedEncodingException ex) { // UTF-8 not supported, highly unlikely
                    System.err.println(ex);
                    System.exit(2);
                }
            }
        }
        return new Query(q);
    }

    public static Query empty() { return new Query(Collections.emptyMap()); }
}
