/*
 * 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.swift.v1.binders;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.ACCOUNT_METADATA_PREFIX;
import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.CONTAINER_METADATA_PREFIX;
import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.OBJECT_METADATA_PREFIX;

import java.util.Map;
import java.util.Map.Entry;

import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;

import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;

/**
 * Will lower-case header keys due to a swift implementation to return headers
 * in a different case than sent. ex.
 * 
 * <pre>
 * >> X-Account-Meta-MyDelete1: foo
 * >> X-Account-Meta-MyDelete2: bar
 * </pre>
 * 
 * results in:
 * 
 * <pre>
 * << X-Account-Meta-Mydelete1: foo
 * << X-Account-Meta-Mydelete2: bar
 * </pre>
 * 
 * <h4>Note</h4> <br/>
 * HTTP response headers keys are known to be case-insensitive, but this
 * practice of mixing up case will prevent metadata keys such as those in
 * Turkish from working.
 */
public class BindMetadataToHeaders implements Binder {

   public static class BindAccountMetadataToHeaders extends BindMetadataToHeaders {
      BindAccountMetadataToHeaders() {
         super(ACCOUNT_METADATA_PREFIX);
      }
   }

   public static class BindRemoveAccountMetadataToHeaders extends BindMetadataToHeaders.ForRemoval {
      BindRemoveAccountMetadataToHeaders() {
         super(ACCOUNT_METADATA_PREFIX);
      }
   }

   public static class BindContainerMetadataToHeaders extends BindMetadataToHeaders {
      BindContainerMetadataToHeaders() {
         super(CONTAINER_METADATA_PREFIX);
      }
   }

   public static class BindRemoveContainerMetadataToHeaders extends BindMetadataToHeaders.ForRemoval {
      BindRemoveContainerMetadataToHeaders() {
         super(CONTAINER_METADATA_PREFIX);
      }
   }

   public static class BindObjectMetadataToHeaders extends BindMetadataToHeaders {
      BindObjectMetadataToHeaders() {
         super(OBJECT_METADATA_PREFIX);
      }
   }

   public static class BindRemoveObjectMetadataToHeaders extends BindMetadataToHeaders.ForRemoval {
      BindRemoveObjectMetadataToHeaders() {
         super(OBJECT_METADATA_PREFIX);
      }
   }

   /**
    * @see <a
    *      href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/delete-account-metadata.html">documentation</a>
    */
   public abstract static class ForRemoval extends BindMetadataToHeaders {
      ForRemoval(String metadataPrefix) {
         super(metadataPrefix);
      }

      @Override
      protected void putMetadata(Builder<String, String> headers, String key, String value) {
         headers.put(String.format("x-remove%s", key.substring(1)), "ignored");
      }
   }

   private final String metadataPrefix;

   public BindMetadataToHeaders(String metadataPrefix) {
      this.metadataPrefix = checkNotNull(metadataPrefix, "metadataPrefix");
   }

   @SuppressWarnings("unchecked")
   @Override
   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
      checkNotNull(request, "request");
      checkArgument(input instanceof Map<?, ?>, "input must be a non-null java.util.Map!");
      Map<String, String> metadata = Map.class.cast(input);
      ImmutableMultimap<String, String> headers = toHeaders(metadata);
      return (R) request.toBuilder().replaceHeaders(headers).build();
   }

   protected void putMetadata(Builder<String, String> headers, String key, String value) {
      headers.put(key, value);
   }

   public ImmutableMultimap<String, String> toHeaders(Map<String, String> metadata) {
      Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
      for (Entry<String, String> keyVal : metadata.entrySet()) {
         String keyInLowercase = keyVal.getKey().toLowerCase();
         if (keyVal.getKey().startsWith(metadataPrefix)) {
            putMetadata(builder, keyInLowercase, keyVal.getValue());
         } else {
            putMetadata(builder, String.format("%s%s", metadataPrefix, keyInLowercase), keyVal.getValue());
         }
      }
      return builder.build();
   }
}
