/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package com.skelril.skree.service.internal.highscore;

import com.skelril.nitro.Clause;
import com.skelril.skree.SkreePlugin;
import com.skelril.skree.service.HighScoreService;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.profile.GameProfile;
import org.spongepowered.api.scheduler.Task;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.LinkedBlockingDeque;

public class HighScoreServiceImpl implements HighScoreService {
  private LinkedBlockingDeque<HighScoreUpdate> highScoreUpdates = new LinkedBlockingDeque<>();

  public HighScoreServiceImpl() {
    Task.builder().execute(() -> {
      while (!highScoreUpdates.isEmpty()) {
        highScoreUpdates.poll().process();
      }
    }).intervalTicks(20).async().submit(SkreePlugin.inst());
  }

  @Override
  public Optional<Integer> get(Player player, ScoreType scoreType) {
    return HighScoreDatabaseUtil.get(player.getUniqueId(), scoreType);
  }

  @Override
  public void update(Player player, ScoreType scoreType, int value) {
    highScoreUpdates.add(new HighScoreUpdate(player.getUniqueId(), scoreType, value));
  }

  @Override
  public List<Clause<Optional<GameProfile>, Integer>> getTop(ScoreType scoreType, int amt) {
    return HighScoreDatabaseUtil.getTop(scoreType, amt);
  }
}

@@ -534,16 +534,44 @@
 .Task;%0A%0A
+import java.util.ArrayList;%0A
 import j
@@ -640,35 +640,75 @@
 current.
-LinkedBlockingDeque
+locks.Lock;%0Aimport java.util.concurrent.locks.ReentrantLock
 ;%0A%0Apubli
@@ -777,34 +777,71 @@
 rivate L
-inkedBlockingDeque
+ock highScoreLock = new ReentrantLock();%0A  private List
 %3CHighSco
@@ -877,27 +877,17 @@
 new 
-LinkedBlockingDeque
+ArrayList
 %3C%3E()
@@ -968,96 +968,290 @@
     
-w
 hi
-le (!highScoreUpdates.isEmpty()) %7B%0A        highScoreUpdates.poll().process();%0A      %7D
+ghScoreLock.lock();%0A%0A      List%3CHighScoreUpdate%3E scoresToUpdate;%0A      try %7B%0A        scoresToUpdate = highScoreUpdates;%0A        highScoreUpdates = new ArrayList%3C%3E();%0A      %7D finally %7B%0A        highScoreLock.unlock();%0A      %7D%0A%0A      scoresToUpdate.forEach(HighScoreUpdate::process);
 %0A   
@@ -1462,32 +1462,214 @@
 coreType);%0A  %7D%0A%0A
+  private void queueUpdate(HighScoreUpdate update) %7B%0A    highScoreLock.lock();%0A    try %7B%0A      highScoreUpdates.add(update);%0A    %7D finally %7B%0A      highScoreLock.unlock();%0A    %7D%0A  %7D%0A%0A
   @Override%0A  pu
@@ -1738,36 +1738,27 @@
 ) %7B%0A    
-highScor
+queu
 eUpdate
-s.add
 (new Hig

Use a custom locking solution to reduce lock contention