/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.jclouds.openstack.nova.v2_0.config;

import java.beans.ConstructorProperties;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.inject.Singleton;

import com.google.common.collect.Maps;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.config.GsonModule;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.openstack.nova.v2_0.domain.Address;
import org.jclouds.openstack.nova.v2_0.domain.BlockDeviceMapping;
import org.jclouds.openstack.nova.v2_0.domain.HostResourceUsage;
import org.jclouds.openstack.nova.v2_0.domain.Image;
import org.jclouds.openstack.nova.v2_0.domain.Server;
import org.jclouds.openstack.nova.v2_0.domain.ServerExtendedAttributes;
import org.jclouds.openstack.nova.v2_0.domain.ServerExtendedStatus;
import org.jclouds.openstack.nova.v2_0.domain.ServerWithSecurityGroups;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.openstack.v2_0.domain.Resource;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;

public class NovaParserModule extends AbstractModule {

   @Provides
   @Singleton
   public final Map<Type, Object> provideCustomAdapterBindings() {
      return ImmutableMap.<Type, Object>of(
              HostResourceUsage.class, new HostResourceUsageAdapter(),
              ServerWithSecurityGroups.class, new ServerWithSecurityGroupsAdapter(),
              Server.class, new ServerAdapter(),
              Image.class, new ImageAdapter()
      );
   }

   @Override
   protected void configure() {
      bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
   }

   @Singleton
   public static class HostResourceUsageAdapter implements JsonSerializer<HostResourceUsage>, JsonDeserializer<HostResourceUsage> {
      public HostResourceUsage apply(HostResourceUsageView in) {
         return in.resource.toBuilder().build();
      }

      @Override
      public HostResourceUsage deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
         return apply((HostResourceUsageView) context.deserialize(jsonElement, HostResourceUsageView.class));
      }

      @Override
      public JsonElement serialize(HostResourceUsage hostResourceUsage, Type type, JsonSerializationContext context) {
         return context.serialize(hostResourceUsage);
      }

      private static class HostResourceUsageView {
         protected HostResourceUsageInternal resource;
      }

      private static class HostResourceUsageInternal extends HostResourceUsage {

         @ConstructorProperties({
                 "host", "project", "memory_mb", "cpu", "disk_gb"
         })
         protected HostResourceUsageInternal(String host, @Nullable String project, int memoryMb, int cpu, int diskGb) {
            super(host, project, memoryMb, cpu, diskGb);
         }
      }
   }

   @Singleton
   public static class ServerWithSecurityGroupsAdapter implements JsonDeserializer<ServerWithSecurityGroups> {
      @Override
      public ServerWithSecurityGroups deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
              throws JsonParseException {
         Server server = context.deserialize(jsonElement, Server.class);
         ServerWithSecurityGroups.Builder<?> result = ServerWithSecurityGroups.builder().fromServer(server);
         Set<String> names = Sets.newLinkedHashSet();
         if (jsonElement.getAsJsonObject().get("security_groups") != null) {
            JsonArray x = jsonElement.getAsJsonObject().get("security_groups").getAsJsonArray();
            for (JsonElement y : x) {
               names.add(y.getAsJsonObject().get("name").getAsString());
            }
            result.securityGroupNames(names);
         }
         return result.build();
      }
   }

   @Singleton
   public static class ServerAdapter implements JsonDeserializer<Server> {
      @Override
      public Server deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
              throws JsonParseException {
         Server serverBase;

         // Servers can be created without an image so test if an image object is returned
         if (jsonElement.getAsJsonObject().get("image").isJsonObject()) {
            serverBase = apply((ServerInternal) context.deserialize(jsonElement, ServerInternal.class));
         } else {
            serverBase = apply((ServerInternalWithoutImage) context.deserialize(jsonElement, ServerInternalWithoutImage.class));
         }

         Server.Builder<?> result = Server.builder().fromServer(serverBase);
         ServerExtendedStatus extendedStatus = context.deserialize(jsonElement, ServerExtendedStatus.class);
         if (!Objects.equal(extendedStatus, ServerExtendedStatus.builder().build())) {
            result.extendedStatus(extendedStatus);
         }
         ServerExtendedAttributes extraAttributes = context.deserialize(jsonElement, ServerExtendedAttributes.class);
         if (!Objects.equal(extraAttributes, ServerExtendedAttributes.builder().build())) {
            result.extendedAttributes(extraAttributes);
         }
         return result.build();
      }

      public Server apply(Server in) {
         return in.toBuilder().build();
      }

      private static class ServerInternal extends Server {
         @ConstructorProperties({"id", "name", "links", "uuid", "tenant_id", "user_id", "updated", "created", "hostId", "accessIPv4", "accessIPv6", "status", "image", "flavor", "key_name", "config_drive", "addresses", "metadata", "extendedStatus", "extendedAttributes", "OS-DCF:diskConfig", "OS-EXT-AZ:availability_zone"})
         protected ServerInternal(String id, @Nullable String name, java.util.Set<Link> links, @Nullable String uuid, String tenantId,
                                  String userId, Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
                                  @Nullable String accessIPv6, Server.Status status, Resource image, Resource flavor, @Nullable String keyName,
                                  @Nullable String configDrive, Multimap<String, Address> addresses, Map<String, String> metadata,
                                  @Nullable ServerExtendedStatus extendedStatus, @Nullable ServerExtendedAttributes extendedAttributes, @Nullable String diskConfig, @Nullable String availabilityZone) {
            super(id, name, links, uuid, tenantId, userId, updated, created, hostId, accessIPv4, accessIPv6, status, image, flavor, keyName, configDrive, addresses, metadata, extendedStatus, extendedAttributes, diskConfig, availabilityZone);
         }
      }

      private static class ServerInternalWithoutImage extends Server {
         @ConstructorProperties({"id", "name", "links", "uuid", "tenant_id", "user_id", "updated", "created", "hostId", "accessIPv4", "accessIPv6", "status", "flavor", "key_name", "config_drive", "addresses", "metadata", "extendedStatus", "extendedAttributes", "OS-DCF:diskConfig", "OS-EXT-AZ:availability_zone"})
         protected ServerInternalWithoutImage(String id, @Nullable String name, java.util.Set<Link> links, @Nullable String uuid, String tenantId,
                                  String userId, Date updated, Date created, @Nullable String hostId, @Nullable String accessIPv4,
                                  @Nullable String accessIPv6, Server.Status status, Resource flavor, @Nullable String keyName,
                                  @Nullable String configDrive, Multimap<String, Address> addresses, Map<String, String> metadata,
                                  @Nullable ServerExtendedStatus extendedStatus, @Nullable ServerExtendedAttributes extendedAttributes, @Nullable String diskConfig, @Nullable String availabilityZone) {
            super(id, name, links, uuid, tenantId, userId, updated, created, hostId, accessIPv4, accessIPv6, status, null, flavor, keyName, configDrive, addresses, metadata, extendedStatus, extendedAttributes, diskConfig, availabilityZone);
         }
      }
   }

   @Singleton
   public static class ImageAdapter implements JsonDeserializer<Image> {
      public static final String METADATA = "metadata";
      public static final String BLOCK_DEVICE_MAPPING = "block_device_mapping";

      @Override
      public Image deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
              throws JsonParseException {
         JsonObject json = jsonElement.getAsJsonObject();
         Map<String, String> metadata = null;
         List<BlockDeviceMapping> blockDeviceMapping = null;

         JsonElement meta = json.get(METADATA);
         if (meta != null && meta.isJsonObject()) {
            metadata = Maps.newTreeMap();
            for (Map.Entry<String, JsonElement> e : meta.getAsJsonObject().entrySet()) {
               Object value;
               if (e.getValue().isJsonArray()) {
                  value = context.deserialize(e.getValue().getAsJsonArray(), ArrayList.class);
               } else if (e.getValue().isJsonObject()) {
                  value = context.deserialize(e.getValue().getAsJsonObject(), TreeMap.class);
               } else if (e.getValue().isJsonPrimitive()) {
                  value = e.getValue().getAsJsonPrimitive().getAsString();
               } else {
                  continue;
               }

               //keep non-string members out of normal metadata
               if (value instanceof String) {
                  metadata.put(e.getKey(), (String) value);
               } else if (value instanceof List && BLOCK_DEVICE_MAPPING.equals(e.getKey())) {
                  blockDeviceMapping = context.deserialize(e.getValue(), new TypeToken<List<BlockDeviceMapping>>(){}.getType());
               }
            }
            json.remove(METADATA);
         }

         return apply(context.<ImageInternal>deserialize(json, ImageInternal.class), metadata, blockDeviceMapping);
      }

      public Image apply(ImageInternal in, Map<String, String> metadata, List<BlockDeviceMapping> blockDeviceMapping) {
         return in.toBuilder().metadata(metadata).blockDeviceMapping(blockDeviceMapping).build();
      }

      private static class ImageInternal extends Image {
         @ConstructorProperties({
                 "id", "name", "links", "updated", "created", "tenant_id", "user_id", "status", "progress", "minDisk", "minRam", "blockDeviceMapping", "server", "metadata"
         })
         protected ImageInternal(String id, @Nullable String name, java.util.Set<Link> links, @Nullable Date updated, @Nullable Date created,
                                 String tenantId, @Nullable String userId, @Nullable Status status, int progress, int minDisk, int minRam,
                                 @Nullable List<BlockDeviceMapping> blockDeviceMapping, @Nullable Resource server, @Nullable Map<String, String> metadata) {
            super(id, name, links, updated, created, tenantId, userId, status, progress, minDisk, minRam, blockDeviceMapping, server, metadata);

         }
      }
   }
}
