/*
 * Copyright 2017, Sascha Häberling
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.retrostore.rpc.api;

import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import org.retrostore.client.common.ApiResponse;
import org.retrostore.client.common.ListAppsApiParams;
import org.retrostore.client.common.RetrostoreAppItem;
import org.retrostore.data.app.AppManagement;
import org.retrostore.data.app.AppStoreItem;
import org.retrostore.request.RequestData;
import org.retrostore.rpc.internal.ApiCall;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.retrostore.client.common.RetrostoreAppItem.MediaImage.Type.CASETTE;
import static org.retrostore.client.common.RetrostoreAppItem.MediaImage.Type.DISK;

/**
 * API call to list apps from the store.
 */
public class ListAppsApiCall implements ApiCall<RetrostoreAppItem> {
  private static final Logger LOG = Logger.getLogger("ListAppsApiCall");
  private final AppManagement mAppManagement;

  public ListAppsApiCall(AppManagement appManagement) {
    mAppManagement = appManagement;
  }

  @Override
  public String getName() {
    return "listApps";
  }

  @Override
  public ApiResponse<RetrostoreAppItem> call(RequestData data) {
    ListAppsApiParams params = parseParams(data.getBody());
    if (params == null) {
      return new ApiResponse<>("Cannot parse parameters.");
    }

    // TODO: This is not efficient once we have a large number of apps.
    List<AppStoreItem> allApps = mAppManagement.getAllApps();
    if (allApps.size() - 1 < params.start) {
      return new ApiResponse<>("Parameter 'start' out of range");
    }

    List<RetrostoreAppItem> appItems = new ArrayList<>();
    for (int i = params.start; i < params.start + params.num && i < allApps.size(); ++i) {
      AppStoreItem app = allApps.get(i);
      RetrostoreAppItem item = new RetrostoreAppItem();

      item.id = app.id;
      item.name = app.listing.name;
      item.version = app.listing.versionString;
      item.description = app.listing.description;
      // TODO: Add support for screenshots.
      item.screenshotUrls = new String[0];

      // Create the list of media images for this app (disks and casettes).
      ImmutableList.Builder<RetrostoreAppItem.MediaImage> mediaImagesForClient =
          ImmutableList.builder();
      for (AppStoreItem.MediaImage mediaImage : app.configuration.disk) {
        if (mediaImage == null) {
          continue;
        }
        RetrostoreAppItem.MediaImage mediaImageForClient = new RetrostoreAppItem.MediaImage
            (DISK, mediaImage.data, mediaImage.uploadTime, mediaImage.description);
        mediaImagesForClient.add(mediaImageForClient);
      }

      AppStoreItem.MediaImage cassette = app.configuration.cassette;
      mediaImagesForClient.add(new RetrostoreAppItem.MediaImage(
          CASETTE, cassette.data, cassette.uploadTime, cassette.description));
      item.mediaImages = mediaImagesForClient.build();
      appItems.add(item);
    }
    return new ApiResponse<>(true, "", appItems);
  }

  private ListAppsApiParams parseParams(String params) {
    try {
      return (new Gson()).fromJson(params, ListAppsApiParams.class);
    } catch (Exception ex) {
      LOG.log(Level.WARNING, "Cannot parse params", ex);
      return null;
    }
  }
}

@@ -863,24 +863,95 @@
 oreAppItem;%0A
+import org.retrostore.client.common.RetrostoreAppItem.MediaImage.Type;%0A
 import org.r
@@ -3071,17 +3071,17 @@
 iaImage 
-=
+!
 = null) 
@@ -3096,480 +3096,232 @@
     
-continue;%0A        %7D%0A        RetrostoreAppItem.MediaImage mediaImageForClient = new RetrostoreAppItem.MediaImage%0A            (DISK, mediaImage.data, mediaImage.uploadTime, mediaImage.description);%0A        mediaImagesForClient.add(mediaImageForClient);%0A      %7D%0A%0A      AppStoreItem.MediaImage cassette = app.configuration.cassette;%0A      mediaImagesForClient.add(new RetrostoreAppItem.MediaImage(%0A          CASETTE, cassette.data, cassette.uploadTime, cassette.description));
+mediaImagesForClient.add(toClientType(mediaImage, DISK));%0A        %7D%0A      %7D%0A%0A      AppStoreItem.MediaImage cassette = app.configuration.cassette;%0A      if (cassette != null) %7B%0A        toClientType(cassette, CASETTE);%0A      %7D
 %0A   
@@ -3440,16 +3440,24 @@
 (true, %22
+All good
 %22, appIt
@@ -3717,11 +3717,307 @@
    %7D%0A  %7D
+%0A%0A  private static RetrostoreAppItem.MediaImage toClientType(AppStoreItem.MediaImage mediaImage,%0A                                                           Type type) %7B%0A    return new RetrostoreAppItem.MediaImage(%0A        DISK, mediaImage.data, mediaImage.uploadTime, mediaImage.description);%0A  %7D
 %0A%7D%0A

Fix NPE in listApps call if no casette was specified.