/*
 * Copyright 2007 Netflix, Inc.
 *
 * 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 net.oauth.signature;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthException;
import net.oauth.OAuthMessage;
import net.oauth.OAuthProblemException;
// BEGIN android-changed
// import org.apache.commons.codec.binary.Base64;
import android.util.Base64;
// END android-changed

/**
 * A pair of algorithms for computing and verifying an OAuth digital signature.
 *
 * @author John Kristian
 * @hide
 */
public abstract class OAuthSignatureMethod {

    /** Add a signature to the message. 
     * @throws URISyntaxException 
     * @throws IOException */
    public void sign(OAuthMessage message)
    throws OAuthException, IOException, URISyntaxException {
        message.addParameter(new OAuth.Parameter("oauth_signature",
                getSignature(message)));
    }

    /**
     * Check whether the message has a valid signature.
     * @throws URISyntaxException 
     *
     * @throws OAuthProblemException
     *             the signature is invalid
     */
    public void validate(OAuthMessage message)
    throws IOException, OAuthException, URISyntaxException {
        message.requireParameters("oauth_signature");
        String signature = message.getSignature();
        String baseString = getBaseString(message);
        if (!isValid(signature, baseString)) {
            OAuthProblemException problem = new OAuthProblemException(
                    "signature_invalid");
            problem.setParameter("oauth_signature", signature);
            problem.setParameter("oauth_signature_base_string", baseString);
            problem.setParameter("oauth_signature_method", message
                    .getSignatureMethod());
            throw problem;
        }
    }

    protected String getSignature(OAuthMessage message)
    throws OAuthException, IOException, URISyntaxException {
        String baseString = getBaseString(message);
        String signature = getSignature(baseString);
        // Logger log = Logger.getLogger(getClass().getName());
        // if (log.isLoggable(Level.FINE)) {
        // log.fine(signature + "=getSignature(" + baseString + ")");
        // }
        return signature;
    }

    protected void initialize(String name, OAuthAccessor accessor)
            throws OAuthException {
        String secret = accessor.consumer.consumerSecret;
        if (name.endsWith(_ACCESSOR)) {
            // This code supports the 'Accessor Secret' extensions
            // described in http://oauth.pbwiki.com/AccessorSecret
            final String key = OAuthConsumer.ACCESSOR_SECRET;
            Object accessorSecret = accessor.getProperty(key);
            if (accessorSecret == null) {
                accessorSecret = accessor.consumer.getProperty(key);
            }
            if (accessorSecret != null) {
                secret = accessorSecret.toString();
            }
        }
        if (secret == null) {
            secret = "";
        }
        setConsumerSecret(secret);
    }

    public static final String _ACCESSOR = "-Accessor";

    /** Compute the signature for the given base string. */
    protected abstract String getSignature(String baseString) throws OAuthException;

    /** Decide whether the signature is valid. */
    protected abstract boolean isValid(String signature, String baseString)
            throws OAuthException;

    private String consumerSecret;

    private String tokenSecret;

    protected String getConsumerSecret() {
        return consumerSecret;
    }

    protected void setConsumerSecret(String consumerSecret) {
        this.consumerSecret = consumerSecret;
    }

    public String getTokenSecret() {
        return tokenSecret;
    }

    public void setTokenSecret(String tokenSecret) {
        this.tokenSecret = tokenSecret;
    }

    public static String getBaseString(OAuthMessage message)
            throws IOException, URISyntaxException {
        List<Map.Entry<String, String>> parameters;
        String url = message.URL;
        int q = url.indexOf('?');
        if (q < 0) {
            parameters = message.getParameters();
        } else {
            // Combine the URL query string with the other parameters:
            parameters = new ArrayList<Map.Entry<String, String>>();
            parameters.addAll(OAuth.decodeForm(message.URL.substring(q + 1)));
            parameters.addAll(message.getParameters());
            url = url.substring(0, q);
        }
        return OAuth.percentEncode(message.method.toUpperCase()) + '&'
                + OAuth.percentEncode(normalizeUrl(url)) + '&'
                + OAuth.percentEncode(normalizeParameters(parameters));
    }

    protected static String normalizeUrl(String url) throws URISyntaxException {
        URI uri = new URI(url);
        String scheme = uri.getScheme().toLowerCase();
        String authority = uri.getAuthority().toLowerCase();
        boolean dropPort = (scheme.equals("http") && uri.getPort() == 80)
                           || (scheme.equals("https") && uri.getPort() == 443);
        if (dropPort) {
            // find the last : in the authority
            int index = authority.lastIndexOf(":");
            if (index >= 0) {
                authority = authority.substring(0, index);
            }
        }
        String path = uri.getRawPath();
        if (path == null || path.length() <= 0) {
            path = "/"; // conforms to RFC 2616 section 3.2.2
        }
        // we know that there is no query and no fragment here.
        return scheme + "://" + authority + path;
    }

    protected static String normalizeParameters(
            Collection<? extends Map.Entry> parameters) throws IOException {
        if (parameters == null) {
            return "";
        }
        List<ComparableParameter> p = new ArrayList<ComparableParameter>(
                parameters.size());
        for (Map.Entry parameter : parameters) {
            if (!"oauth_signature".equals(parameter.getKey())) {
                p.add(new ComparableParameter(parameter));
            }
        }
        Collections.sort(p);
        return OAuth.formEncode(getParameters(p));
    }

    // BEGIN android-changed
    public static byte[] decodeBase64(String s) {
        return Base64.decode(s, Base64.DEFAULT);
    }

    public static String base64Encode(byte[] b) {
        return Base64.encodeToString(b, Base64.DEFAULT);
    }
    // END android-changed

    public static OAuthSignatureMethod newSigner(OAuthMessage message,
            OAuthAccessor accessor) throws IOException, OAuthException {
        message.requireParameters(OAuth.OAUTH_SIGNATURE_METHOD);
        OAuthSignatureMethod signer = newMethod(message.getSignatureMethod(),
                accessor);
        signer.setTokenSecret(accessor.tokenSecret);
        return signer;
    }

    /** The factory for signature methods. */
    public static OAuthSignatureMethod newMethod(String name,
            OAuthAccessor accessor) throws OAuthException {
        try {
            Class methodClass = NAME_TO_CLASS.get(name);
            if (methodClass != null) {
                OAuthSignatureMethod method = (OAuthSignatureMethod) methodClass
                .newInstance();
                method.initialize(name, accessor);
                return method;
            }
            OAuthProblemException problem = new OAuthProblemException(
            "signature_method_rejected");
            String acceptable = OAuth.percentEncode(NAME_TO_CLASS.keySet());
            if (acceptable.length() > 0) {
                problem.setParameter("oauth_acceptable_signature_methods",
                        acceptable.toString());
            }
            throw problem;
        } catch (InstantiationException e) {
            throw new OAuthException(e);
        } catch (IllegalAccessException e) {
            throw new OAuthException(e);
        }
    }

    /**
     * Subsequently, newMethod(name) will attempt to instantiate the given
     * class, with no constructor parameters.
     */
    public static void registerMethodClass(String name, Class clazz) {
        NAME_TO_CLASS.put(name, clazz);
    }

    private static final Map<String, Class> NAME_TO_CLASS = new ConcurrentHashMap<String, Class>();
    static {
        registerMethodClass("HMAC-SHA1", HMAC_SHA1.class);
        registerMethodClass("PLAINTEXT", PLAINTEXT.class);
        registerMethodClass("RSA-SHA1", RSA_SHA1.class);
        registerMethodClass("HMAC-SHA1" + _ACCESSOR, HMAC_SHA1.class);
        registerMethodClass("PLAINTEXT" + _ACCESSOR, PLAINTEXT.class);
    }

    /** An efficiently sortable wrapper around a parameter. */
    private static class ComparableParameter implements
            Comparable<ComparableParameter> {

        ComparableParameter(Map.Entry value) {
            this.value = value;
            String n = toString(value.getKey());
            String v = toString(value.getValue());
            this.key = OAuth.percentEncode(n) + ' ' + OAuth.percentEncode(v);
            // ' ' is used because it comes before any character
            // that can appear in a percentEncoded string.
        }

        final Map.Entry value;

        private final String key;

        private static String toString(Object from) {
            return (from == null) ? null : from.toString();
        }

        public int compareTo(ComparableParameter that) {
            return this.key.compareTo(that.key);
        }

        @Override
        public String toString() {
            return key;
        }

    }

    /** Retrieve the original parameters from a sorted collection. */
    private static List<Map.Entry> getParameters(
            Collection<ComparableParameter> parameters) {
        if (parameters == null) {
            return null;
        }
        List<Map.Entry> list = new ArrayList<Map.Entry>(parameters.size());
        for (ComparableParameter parameter : parameters) {
            list.add(parameter.value);
        }
        return list;
    }

}
