package nu.nerd.easyrider;

import java.util.function.BooleanSupplier;

import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Horse;

import nu.nerd.easyrider.db.SavedHorse;

// ----------------------------------------------------------------------------
/**
 * A task that scans all horses in all currently loaded chunks in a specified
 * world.
 */
public class ScanLoadedChunksTask implements BooleanSupplier {
    // ------------------------------------------------------------------------

    public ScanLoadedChunksTask(World world) {
        _world = world;
    }

    // ------------------------------------------------------------------------
    /**
     * @see java.util.function.BooleanSupplier#getAsBoolean()
     */
    @Override
    public boolean getAsBoolean() {
        long start = System.nanoTime();
        long elapsed;
        if (_chunks == null) {
            _chunks = _world.getLoadedChunks();
            if (EasyRider.CONFIG.DEBUG_SCANS) {
                elapsed = System.nanoTime() - start;
                EasyRider.PLUGIN.getLogger().info("Get " + _world.getName() +
                                                  " loaded chunks: " + elapsed * 0.001 + " microseconds.");
            }
            return true;
        }

        int startIndex = _index;
        while (_index < _chunks.length) {
            Chunk chunk = _chunks[_index++];
            if (chunk.isLoaded()) {
                for (Entity entity : chunk.getEntities()) {
                    if (entity instanceof Horse) {
                        Horse horse = (Horse) entity;
                        SavedHorse savedHorse = EasyRider.DB.findHorse(horse);
                        if (savedHorse != null) {
                            EasyRider.DB.observe(savedHorse, horse);
                            if (savedHorse.isAbandoned()) {
                                EasyRider.DB.freeHorse(savedHorse, horse);
                            }
                        }
                    }
                }
            }

            elapsed = System.nanoTime() - start;
            if (elapsed > EasyRider.CONFIG.SCAN_TIME_LIMIT_MICROS * 1000) {
                if (EasyRider.CONFIG.DEBUG_SCANS) {
                    EasyRider.PLUGIN.getLogger().info("Processed " + (_index - startIndex) +
                                                      " chunks in " + elapsed * 0.001 + " microseconds.");
                }
                return true;
            }
        }

        if (EasyRider.CONFIG.DEBUG_SCANS) {
            EasyRider.PLUGIN.getLogger().info("Scan of " + _world.getName() + " complete.");
        }
        return false;
    }

    // ------------------------------------------------------------------------
    /**
     * The World whose chunks are scanned.
     */
    protected World _world;

    /**
     * Array of loaded chunks at the start of the scan.
     */
    protected Chunk[] _chunks;

    /**
     * Index of next chunk to process in _chunks.
     */
    protected int _index;
} // class ScanLoadedChunksTask
@@ -90,16 +90,44 @@
 .Chunk;%0A
+import org.bukkit.Material;%0A
 import o
@@ -207,16 +207,55 @@
 y.Horse;
+%0Aimport org.bukkit.inventory.ItemStack;
 %0A%0Aimport
@@ -608,16 +608,121 @@
 -------%0A
+    /**%0A     * Constructor.%0A     *%0A     * @param world the world whose loaded chunks are scanned.%0A     */
 %0A    pub
@@ -2154,32 +2154,753 @@
               %7D%0A
+                        %7D else if (horse.getOwner() != null) %7B%0A                            // Version 1.7.3 wrongly dropped the record for%0A                            // abandoned horses. Those horses need their owner%0A                            // cleared. Their inv will be empty, at least.%0A                            horse.setOwner(null);%0A                            horse.setTamed(false);%0A                            horse.setDomestication(1);%0A                            if (horse.isCarryingChest()) %7B%0A                                horse.setCarryingChest(false);%0A                                horse.getWorld().dropItemNaturally(horse.getLocation(), new ItemStack(Material.CHEST));%0A                            %7D%0A
                 

Version 1.7.3 dropped DB records for abandoned horses on load. Unfortunately, that doesn't clear the owner of the horse, which also needs to happen.