/*
 * 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.ohai.functions;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

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

import org.jclouds.domain.JsonBall;
import org.jclouds.json.Json;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.inject.TypeLiteral;

@Singleton
public class NestSlashKeys implements Function<Multimap<String, Supplier<JsonBall>>, Map<String, JsonBall>> {

   private final Json json;

   @Inject
   NestSlashKeys(Json json) {
      this.json = checkNotNull(json, "json");
   }

   @Override
   public Map<String, JsonBall> apply(Multimap<String, Supplier<JsonBall>> from) {

      Map<String, JsonBall> autoAttrs = mergeSameKeys(from);

      Map<String, JsonBall> modifiableFlatMap = Maps.newLinkedHashMap(Maps.filterKeys(autoAttrs,
            new Predicate<String>() {

               @Override
               public boolean apply(String input) {
                  return input.indexOf('/') == -1;
               }

            }));
      Map<String, JsonBall> withSlashesMap = Maps.difference(autoAttrs, modifiableFlatMap).entriesOnlyOnLeft();
      for (Entry<String, JsonBall> entry : withSlashesMap.entrySet()) {
         List<String> keyParts = Lists.newArrayList(Splitter.on('/').split(entry.getKey()));
         JsonBall toInsert = entry.getValue();
         try {
            putUnderContext(keyParts, toInsert, modifiableFlatMap);
         } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("error inserting value in entry: " + entry.getKey(), e);
         }
      }
      return modifiableFlatMap;
   }

   private Map<String, JsonBall> mergeSameKeys(Multimap<String, Supplier<JsonBall>> from) {
      Map<String, JsonBall> merged = Maps.newLinkedHashMap();
      for (Entry<String, Supplier<JsonBall>> entry : from.entries()) {
         if (merged.containsKey(entry.getKey())) {
            mergeAsPeer(entry.getKey(), entry.getValue().get(), merged);
         } else {
            merged.put(entry.getKey(), entry.getValue().get());
         }
      }
      return merged;
   }

   @VisibleForTesting
   void mergeAsPeer(String key, JsonBall value, Map<String, JsonBall> insertionContext) {
      Map<String, JsonBall> immutableValueContext = json.fromJson(insertionContext.get(key).toString(), mapLiteral);
      Map<String, JsonBall> valueContext = Maps.newLinkedHashMap(immutableValueContext);
      Map<String, JsonBall> toPut = json.<Map<String, JsonBall>> fromJson(value.toString(), mapLiteral);
      Set<String> uniques = Sets.difference(toPut.keySet(), valueContext.keySet());
      for (String k : uniques) {
         valueContext.put(k, toPut.get(k));
      }
      Set<String> conflicts = Sets.difference(toPut.keySet(), uniques);
      for (String k : conflicts) {
         JsonBall v = toPut.get(k);
         if (v.toString().matches("^\\{.*\\}$")) {
            mergeAsPeer(k, v, valueContext);
         } else {
            // replace
            valueContext.put(k, v);
         }
      }
      insertionContext.put(key, new JsonBall(json.toJson(valueContext, mapLiteral)));
   }

   /**
    * @param keyParts
    * @param toInsert
    * @param destination
    * @throws IllegalArgumentException
    *            <p/>
    *            if destination.get(keyParts(0)) is not a map *
    *            <p/>
    *            keyParts is zero length
    */
   void putUnderContext(List<String> keyParts, JsonBall toInsert, Map<String, JsonBall> destination) {
      checkNotNull(keyParts, "keyParts");
      checkArgument(keyParts.size() >= 1, "keyParts must contain at least one element");

      checkNotNull(toInsert, "toInsert");
      checkNotNull(destination, "destination");

      String rootKey = keyParts.remove(0);
      String rootValue = destination.containsKey(rootKey) ? destination.get(rootKey).toString() : "{}";

      checkArgument(rootValue.matches("^\\{.*\\}$"), "value must be a hash: %s", rootValue);
      Map<String, JsonBall> immutableInsertionContext = json.fromJson(rootValue, mapLiteral);
      Map<String, JsonBall> insertionContext = Maps.newLinkedHashMap(immutableInsertionContext);
      if (keyParts.size() == 1) {
         if (!insertionContext.containsKey(keyParts.get(0))) {
            insertionContext.put(keyParts.get(0), toInsert);
         } else {
            String key = keyParts.get(0);
            mergeAsPeer(key, toInsert, insertionContext);
         }
      } else {
         putUnderContext(keyParts, toInsert, insertionContext);
      }
      destination.put(rootKey, new JsonBall(json.toJson(insertionContext, mapLiteral)));
   }

   final Type mapLiteral = new TypeLiteral<Map<String, JsonBall>>() {
   }.getType();
   final Type listLiteral = new TypeLiteral<List<JsonBall>>() {
   }.getType();
}
