/** Created by frascuchon on 5/11/15. */
@Service
public class AlbumsStoreImpl implements AlbumsStore {

  private ConcurrentMap<String, Album> albums = Maps.newConcurrentMap();

  @Override
  public List<Album> getAll() {
    return Collections.unmodifiableList(new ArrayList<Album>(albums.values()));
  }

  @Override
  public Album findAlbumById(String albumId) {
    return (albums.containsKey(albumId)) ? albums.get(albumId) : null;
  }

  @Override
  public void addAlbum(Album entity) throws Exception {
    if (entity == null || StringUtils.isEmpty(entity.getAlbumId())) {
      throw new IllegalArgumentException();
    } else {
      albums.putIfAbsent(entity.getAlbumId(), entity);
    }
  }

  @Override
  public List<Song> findAlbumSongsById(String albumId) {
    return null;
  }
}
public class PlayerRepositoryImpl implements PlayerRepository {
  private static final String resourceName = "/players.csv";
  private Map<String, Player> playerById = Maps.newConcurrentMap();
  private static Logger logger = LoggerFactory.getLogger(PlayerRepositoryImpl.class);

  private Player fromLine(String[] line) {
    Player m = new Player();
    m.setName(line[0]);
    m.setEmail(line[1]);
    List<String> instruments = Splitter.on(',').splitToList(line[2]);
    for (String i : instruments) {
      Instrument instr = Instrument.valueOf(i);
      if (i != null) m.addPlayedInstrument(instr);
    }
    return m;
  }

  @Override
  @LogPerformances(layer = "domain", operation = "find_player_by_id")
  public Player find(String id) {
    return playerById.get(id);
  }

  @SuppressWarnings("resource")
  @LogPerformances(layer = "domain", operation = "loadFile")
  protected void loadFile() {
    try {
      URL resource = PlayerRepositoryImpl.class.getResource(resourceName);
      CSVReader reader = new CSVReader(new FileReader(resource.getFile()), ';');
      String[] line;
      while ((line = reader.readNext()) != null) {
        logger.info("Loading record '{}'", Joiner.on("//").join(line));
        Player m = fromLine(line);
        playerById.put(m.getId(), m);
      }
    } catch (IOException e) {
      throw new RuntimeException("Unable to read resource;" + resourceName);
    }
  }

  public PlayerRepositoryImpl() {
    loadFile();
  }

  @Override
  @LogPerformances(layer = "domain", operation = "find_player_by_instrument")
  public List<Player> find(Instrument instrument) {
    List<Player> players = Lists.newArrayList();
    for (Map.Entry<String, Player> entry : playerById.entrySet()) {
      if (entry.getValue().getInstruments().contains(instrument)) players.add(entry.getValue());
    }
    return players;
  }

  @Override
  @LogPerformances(layer = "domain", operation = "find_player_by_instrument_category")
  public List<Player> find(Category instrumentCategory) {
    Set<Player> players = Sets.newHashSet();

    for (Map.Entry<String, Player> entry : playerById.entrySet()) {
      for (Instrument inst : entry.getValue().getInstruments()) {
        if (inst.getCategory().equals(instrumentCategory)) players.add(entry.getValue());
      }
    }
    return Lists.newArrayList(players);
  }

  @Override
  @LogPerformances(layer = "domain", operation = "find_all_players")
  public List<Player> list() {
    return ImmutableList.copyOf(playerById.values());
  }
}