/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2016, Max Roncace <me@caseif.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package net.caseif.ttt.util;

import static net.caseif.ttt.util.Constants.MetadataTag.ARENA_ROUND_TALLY;
import static net.caseif.ttt.util.Constants.MetadataTag.ARENA_START_TIME;

import net.caseif.ttt.TTTCore;
import net.caseif.ttt.util.config.OperatingMode;
import net.caseif.ttt.util.helper.gamemode.ArenaHelper;

import net.caseif.flint.arena.Arena;
import net.caseif.flint.challenger.Challenger;
import net.caseif.flint.round.Round;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

/**
 * Daemon used to restart rounds after they've ended when the server is
 * operating in {@link OperatingMode#CONTINUOUS} or {OperatingMode#DEDICATED}
 * mode.
 */
public class RoundRestartDaemon extends BukkitRunnable {

    private Arena arena;

    private final Set<UUID> players = new HashSet<>();

    boolean willCycle = false;

    public RoundRestartDaemon(Round round) {
        super();

        this.arena = round.getArena();
        arena.getMetadata().set(ARENA_ROUND_TALLY, arena.getMetadata().<Integer>get(ARENA_ROUND_TALLY).get() + 1);
        willCycle = TTTCore.config.OPERATING_MODE == OperatingMode.DEDICATED && shouldArenaBeCycled();

        for (Challenger ch : round.getChallengers()) {
            players.add(ch.getUniqueId());
        }
    }

    @Override
    public void run() {
        assert !arena.getRound().isPresent(); // it shouldn't contain a round before the daemon runs

        if (willCycle) {
            cycleArena();
        }

        Round round = arena.createRound();
        for (UUID uuid : players) {
            round.addChallenger(uuid);
        }
    }

    private boolean shouldArenaBeCycled() {
        int timeLimit = TTTCore.config.CYCLE_TIME_LIMIT;
        int roundLimit = TTTCore.config.CYCLE_ROUND_LIMIT;

        if (timeLimit >= 0 && (TTTCore.config.CYCLE_TIME_LIMIT >= 0)
                && (System.currentTimeMillis() - arena.getMetadata().<Long>get(ARENA_START_TIME).get())
                >= (timeLimit * 60 * 1000)) { // I realize that was super-ugly
            arena.getMetadata().remove(ARENA_START_TIME);
            return true; // time limit reached
        } else if (roundLimit >= 0 && arena.getMetadata().<Integer>get(ARENA_ROUND_TALLY).get() - 1 >= roundLimit) {
            arena.getMetadata().set(ARENA_ROUND_TALLY, 1);
            return true; // round limit reached
        }

        return false;
    }

    private void cycleArena() {
        this.arena.getMetadata().remove(ARENA_START_TIME);
        this.arena.getMetadata().remove(ARENA_ROUND_TALLY);
        ArenaHelper.applyNextArena();
        this.arena = TTTCore.getDedicatedArena();
    }

}

@@ -2026,16 +2026,30 @@
 );%0A%0A    
+private final 
 boolean 
@@ -2061,16 +2061,47 @@
 ycle
- = false
+;%0A    private final boolean willRestart
 ;%0A%0A 
@@ -2179,34 +2179,174 @@
 his.
-arena = round.getArena();%0A
+willRestart = round.getChallengers().size() %3E 0;%0A%0A        this.arena = round.getArena();%0A%0A        if (TTTCore.config.OPERATING_MODE == OperatingMode.DEDICATED) %7B%0A    
     
@@ -2464,16 +2464,25 @@
         
+    this.
 willCycl
@@ -2489,92 +2489,131 @@
 e = 
-TTTCore.config.OPERATING_MODE == OperatingMode.DEDICATED && shouldArenaBeCycled();%0A%0A
+shouldArenaBeCycled();%0A        %7D else %7B%0A            this.willCycle = false;%0A        %7D%0A%0A        if (this.willRestart) %7B%0A    
     
@@ -2675,16 +2675,20 @@
         
+    
 players.
@@ -2710,16 +2710,30 @@
 eId());%0A
+            %7D%0A
         
@@ -2935,32 +2935,68 @@
 a();%0A        %7D%0A%0A
+        if (this.willRestart) %7B%0A    
         Round ro
@@ -3026,24 +3026,28 @@
 ();%0A        
+ 
+   
 for (UUID uu
@@ -3058,24 +3058,28 @@
  players) %7B%0A
+    
             
@@ -3105,16 +3105,30 @@
 (uuid);%0A
+            %7D%0A
         
@@ -3775,67 +3775,8 @@
 ) %7B%0A
-            arena.getMetadata().set(ARENA_ROUND_TALLY, 1);%0A
     

Fix plugin restarting empty rounds in continuous or dedicated mode