/*
 * This file is part of ActionFoto.
 * Copyright (c) 2018-2022. SBDevelopment - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 * Written by Stijn Bannink <stijnbannink23@gmail.com>, April 2022
 */

package nl.sbdeveloper.themeparkplus.sbutils;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Purchase verification class
 *
 * @author Stijn [SBDeveloper]
 * @version 2.0 [17-04-2022] - Updated to Polymart
 * @since 23-12-2019
 */
public class Verify implements Listener {
    private static final String endpointURL = "https://api.polymart.org/v1/verifyPurchase/?inject_version=%d&resource_id=%d&user_id=%d&nonce=%d&download_agent=%d&download_time=%d&download_token=%s";

    private final JavaPlugin plugin; // The plugin instance

    private final int resourceID;
    private final int injector_version;
    private final int user_id;
    private final int nonce;
    private final int download_agent;
    private final int download_time;
    private final String download_token;

    private String invalidReason = null; // The reason the license is invalid, if null it's not invalid!
    private static Boolean valid = null; // If true, it's valid, if false, it's not valid, if null it's not checked!

    /**
     * Construct a new license
     *
     * @param plugin The plugin
     */
    public Verify(JavaPlugin plugin) {
        this.plugin = plugin;

        this.resourceID = Integer.parseInt("%%__RESOURCE__%%");
        this.injector_version = Integer.parseInt("%%__INJECT_VER__%%");
        this.user_id = Integer.parseInt("%%__USER__%%");
        this.nonce = Integer.parseInt("%%__NONCE__%%");
        this.download_agent = Integer.parseInt("%%__AGENT__%%");
        this.download_time = Integer.parseInt("%%__TIMESTAMP__%%");
        this.download_token = "%%__VERIFY_TOKEN__%%";

        Bukkit.getPluginManager().registerEvents(this, plugin);

        validate();
    }

    @EventHandler
    public void onJoin(PlayerJoinEvent e) {
        if (this.invalidReason == null) return;

        Player p = e.getPlayer();
        if (p.isOp() || p.hasPermission("sbd.licensemessages")) {
            Bukkit.getScheduler().runTaskLater(this.plugin, () -> p.sendMessage(ChatColor.GOLD + "[" + ChatColor.RED + this.plugin.getName() + ChatColor.GOLD + "] " + ChatColor.RED + "The license is incorrect! Reason: " + ChatColor.GOLD + this.invalidReason), 5 * 20L /* 5 sec */);
        }
    }

    /**
     * Validate the purchase
     */
    private void validate() {
        try {
            URL url = new URL(String.format(endpointURL, this.injector_version, this.resourceID, this.user_id, this.nonce, this.download_agent, this.download_time, this.download_token));
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            con.setRequestProperty("User-Agent", "SBDVerify/2.0");
            con.setConnectTimeout(5000); //Timeout after 5 sec.
            con.setReadTimeout(5000); //Timeout after 5 sec.
            int code = con.getResponseCode();
            if (code != 200) {
                disable("Could not send the validating request.");
                return;
            }
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            JsonObject json = new JsonParser().parse(response.toString()).getAsJsonObject();
            if (json == null) {
                disable("Could not send the validating request.");
                return;
            }

            if (!json.has("response")) {
                disable("An invalid response was returned by the validating request.");
                return;
            }

            JsonObject resp = json.get("response").getAsJsonObject();
            if (!resp.has("success")) {
                disable("An invalid response was returned by the validating request.");
                return;
            }

            if (!resp.get("success").getAsBoolean()) {
                disable("The purchase of this plugin could not be verified.");
            }
        } catch (IOException e) {
            disable("Could not send the validating request.");
        }
    }

    /**
     * Disable the plugin (private)
     *
     * @param reason The disabling reason
     */
    private void disable(String reason) {
        this.invalidReason = reason;

        Bukkit.getScheduler().runTask(this.plugin, () -> {
            valid = false;

            plugin.getLogger().severe("Stopping plugin because licensing system check failed.");
            plugin.getLogger().severe("Reason: " + reason);
            plugin.getLogger().severe("Contact the developer if you believe something is wrong on their side.");
            Bukkit.getPluginManager().disablePlugin(this.plugin);
        });
    }

    /**
     * Check if the license is valid
     *
     * @return true = VALID, false = INVALID, null = UNCHECKED
     */
    public Boolean isValidated() {
        return this.invalidReason == null;
    }

    /**
     * Check if the license is valid
     *
     * @return true = VALID, false = INVALID, null = UNCHECKED
     */
    public static Boolean isValid() {
        return valid;
    }
}