/*
 * 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.chef.config;

import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.jclouds.chef.domain.DatabagItem;
import org.jclouds.chef.functions.ParseCookbookDefinitionFromJson;
import org.jclouds.chef.functions.ParseCookbookVersionsV09FromJson;
import org.jclouds.chef.functions.ParseCookbookVersionsV10FromJson;
import org.jclouds.chef.functions.ParseKeySetFromJson;
import org.jclouds.chef.suppliers.ChefVersionSupplier;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.http.HttpResponse;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory;
import org.jclouds.json.internal.NullHackJsonLiteralAdapter;

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.io.ByteSource;
import com.google.gson.Gson;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.JsonReaderInternalAccess;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy;
import com.google.inject.Provides;

public class ChefParserModule extends AbstractModule {
   @ImplementedBy(PrivateKeyAdapterImpl.class)
   public interface PrivateKeyAdapter extends JsonDeserializer<PrivateKey> {

   }

   @Singleton
   public static class PrivateKeyAdapterImpl implements PrivateKeyAdapter {
      private final Crypto crypto;

      @Inject
      PrivateKeyAdapterImpl(Crypto crypto) {
         this.crypto = crypto;
      }

      @Override
      public PrivateKey deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
         String keyText = json.getAsString().replaceAll("\\n", "\n");
         try {
            return crypto.rsaKeyFactory().generatePrivate(
                  Pems.privateKeySpec(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8))));
         } catch (UnsupportedEncodingException e) {
            Throwables.propagate(e);
            return null;
         } catch (InvalidKeySpecException e) {
            Throwables.propagate(e);
            return null;
         } catch (IOException e) {
            Throwables.propagate(e);
            return null;
         }
      }
   }

   @ImplementedBy(PublicKeyAdapterImpl.class)
   public interface PublicKeyAdapter extends JsonDeserializer<PublicKey> {

   }

   @Singleton
   public static class PublicKeyAdapterImpl implements PublicKeyAdapter {
      private final Crypto crypto;

      @Inject
      PublicKeyAdapterImpl(Crypto crypto) {
         this.crypto = crypto;
      }

      @Override
      public PublicKey deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
         String keyText = json.getAsString().replaceAll("\\n", "\n");
         try {
            return crypto.rsaKeyFactory().generatePublic(
                  Pems.publicKeySpec(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8))));
         } catch (UnsupportedEncodingException e) {
            Throwables.propagate(e);
            return null;
         } catch (InvalidKeySpecException e) {
            Throwables.propagate(e);
            return null;
         } catch (IOException e) {
            Throwables.propagate(e);
            return null;
         }
      }
   }

   @ImplementedBy(X509CertificateAdapterImpl.class)
   public interface X509CertificateAdapter extends JsonDeserializer<X509Certificate> {

   }

   @Singleton
   public static class X509CertificateAdapterImpl implements X509CertificateAdapter {
      private final Crypto crypto;

      @Inject
      X509CertificateAdapterImpl(Crypto crypto) {
         this.crypto = crypto;
      }

      @Override
      public X509Certificate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
         String keyText = json.getAsString().replaceAll("\\n", "\n");
         try {
            return Pems.x509Certificate(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8)),
                  crypto.certFactory());
         } catch (UnsupportedEncodingException e) {
            Throwables.propagate(e);
            return null;
         } catch (IOException e) {
            Throwables.propagate(e);
            return null;
         } catch (CertificateException e) {
            Throwables.propagate(e);
            return null;
         }
      }
   }

   /**
    * writes or reads the literal directly
    */
   @Singleton
   public static class DataBagItemAdapter extends NullHackJsonLiteralAdapter<DatabagItem> {
      final Gson gson = new Gson();

      @Override
      protected DatabagItem createJsonLiteralFromRawJson(String text) {
         IdHolder idHolder = gson.fromJson(text, IdHolder.class);
         checkState(idHolder.id != null,
               "databag item must be a json hash ex. {\"id\":\"item1\",\"my_key\":\"my_data\"}; was %s", text);
         text = text.replaceFirst(String.format("\\{\"id\"[ ]?:\"%s\",", idHolder.id), "{");
         return new DatabagItem(idHolder.id, text);
      }

      @Override
      protected String toString(DatabagItem value) {
         String text = value.toString();

         try {
            IdHolder idHolder = gson.fromJson(text, IdHolder.class);
            if (idHolder.id == null) {
               text = text.replaceFirst("\\{", String.format("{\"id\":\"%s\",", value.getId()));
            } else {
               checkArgument(value.getId().equals(idHolder.id),
                     "incorrect id in databagItem text, should be %s: was %s", value.getId(), idHolder.id);
            }
         } catch (JsonSyntaxException e) {
            throw new IllegalArgumentException(e);
         }

         return text;
      }
   }

   private static class IdHolder {
      private String id;
   }

   // The NullFilteringTypeAdapterFactories.MapTypeAdapter class is final. Do
   // the same logic here
   private static final class KeepLastRepeatedKeyMapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {

      protected final TypeAdapter<K> keyAdapter;
      protected final TypeAdapter<V> valueAdapter;

      protected KeepLastRepeatedKeyMapTypeAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
         this.keyAdapter = keyAdapter;
         this.valueAdapter = valueAdapter;
         nullSafe();
      }

      public void write(JsonWriter out, Map<K, V> value) throws IOException {
         if (value == null) {
            out.nullValue();
            return;
         }
         out.beginObject();
         for (Map.Entry<K, V> element : value.entrySet()) {
            out.name(String.valueOf(element.getKey()));
            valueAdapter.write(out, element.getValue());
         }
         out.endObject();
      }

      public Map<K, V> read(JsonReader in) throws IOException {
         Map<K, V> result = Maps.newHashMap();
         in.beginObject();
         while (in.hasNext()) {
            JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
            K name = keyAdapter.read(in);
            V value = valueAdapter.read(in);
            if (value != null) {
               // If there are repeated keys, overwrite them to only keep the last one
               result.put(name, value);
            }
         }
         in.endObject();
         return ImmutableMap.copyOf(result);
      }

      @Override
      public int hashCode() {
         return Objects.hashCode(keyAdapter, valueAdapter);
      }

      @Override
      public boolean equals(Object obj) {
         if (this == obj)
            return true;
         if (obj == null || getClass() != obj.getClass())
            return false;
         KeepLastRepeatedKeyMapTypeAdapter<?, ?> that = KeepLastRepeatedKeyMapTypeAdapter.class.cast(obj);
         return equal(this.keyAdapter, that.keyAdapter) && equal(this.valueAdapter, that.valueAdapter);
      }

      @Override
      public String toString() {
         return toStringHelper(this).add("keyAdapter", keyAdapter).add("valueAdapter", valueAdapter).toString();
      }
   }

   public static class KeepLastRepeatedKeyMapTypeAdapterFactory extends MapTypeAdapterFactory {

      public KeepLastRepeatedKeyMapTypeAdapterFactory() {
         super(Map.class);
      }

      @SuppressWarnings("unchecked")
      @Override
      protected <K, V, T> TypeAdapter<T> newAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
         return (TypeAdapter<T>) new KeepLastRepeatedKeyMapTypeAdapter<K, V>(keyAdapter, valueAdapter);
      }
   }

   @Provides
   @Singleton
   public Map<Type, Object> provideCustomAdapterBindings(DataBagItemAdapter adapter, PrivateKeyAdapter privateAdapter,
         PublicKeyAdapter publicAdapter, X509CertificateAdapter certAdapter) {
      return ImmutableMap.<Type, Object> of(DatabagItem.class, adapter, PrivateKey.class, privateAdapter,
            PublicKey.class, publicAdapter, X509Certificate.class, certAdapter);
   }

   @Provides
   @Singleton
   @CookbookParser
   public Function<HttpResponse, Set<String>> provideCookbookDefinitionAdapter(ChefVersionSupplier chefVersionSupplier,
         ParseCookbookDefinitionFromJson v10parser, ParseKeySetFromJson v09parser) {
      return chefVersionSupplier.get() >= 10 ? v10parser : v09parser;
   }

   @Provides
   @Singleton
   @CookbookVersionsParser
   public Function<HttpResponse, Set<String>> provideCookbookDefinitionAdapter(ChefVersionSupplier chefVersionSupplier,
         ParseCookbookVersionsV10FromJson v10parser, ParseCookbookVersionsV09FromJson v09parser) {
      return chefVersionSupplier.get() >= 10 ? v10parser : v09parser;
   }

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