/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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 android.net;

import android.os.ServiceManager;
import android.util.Log;

import com.android.net.IProxyService;
import com.google.android.collect.Lists;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

/**
 * @hide
 */
public class PacProxySelector extends ProxySelector {
    private static final String TAG = "PacProxySelector";
    public static final String PROXY_SERVICE = "com.android.net.IProxyService";
    private static final String SOCKS = "SOCKS ";
    private static final String PROXY = "PROXY ";

    private IProxyService mProxyService;
    private final List<Proxy> mDefaultList;

    public PacProxySelector() {
        mProxyService = IProxyService.Stub.asInterface(
                ServiceManager.getService(PROXY_SERVICE));
        if (mProxyService == null) {
            // Added because of b10267814 where mako is restarting.
            Log.e(TAG, "PacManager: no proxy service");
        }
        mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY);
    }

    @Override
    public List<Proxy> select(URI uri) {
        if (mProxyService == null) {
            mProxyService = IProxyService.Stub.asInterface(
                    ServiceManager.getService(PROXY_SERVICE));
        }
        if (mProxyService == null) {
            Log.e(TAG, "select: no proxy service return NO_PROXY");
            return Lists.newArrayList(java.net.Proxy.NO_PROXY);
        }
        String response = null;
        String urlString;
        try {
            // Strip path and username/password from URI so it's not visible to PAC script. The
            // path often contains credentials the app does not want exposed to a potentially
            // malicious PAC script.
            if (!"http".equalsIgnoreCase(uri.getScheme())) {
                uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null);
            }
            urlString = uri.toURL().toString();
        } catch (URISyntaxException e) {
            urlString = uri.getHost();
        } catch (MalformedURLException e) {
            urlString = uri.getHost();
        }
        try {
            response = mProxyService.resolvePacFile(uri.getHost(), urlString);
        } catch (Exception e) {
            Log.e(TAG, "Error resolving PAC File", e);
        }
        if (response == null) {
            return mDefaultList;
        }

        return parseResponse(response);
    }

    private static List<Proxy> parseResponse(String response) {
        String[] split = response.split(";");
        List<Proxy> ret = Lists.newArrayList();
        for (String s : split) {
            String trimmed = s.trim();
            if (trimmed.equals("DIRECT")) {
                ret.add(java.net.Proxy.NO_PROXY);
            } else if (trimmed.startsWith(PROXY)) {
                Proxy proxy = proxyFromHostPort(Type.HTTP, trimmed.substring(PROXY.length()));
                if (proxy != null) {
                    ret.add(proxy);
                }
            } else if (trimmed.startsWith(SOCKS)) {
                Proxy proxy = proxyFromHostPort(Type.SOCKS, trimmed.substring(SOCKS.length()));
                if (proxy != null) {
                    ret.add(proxy);
                }
            }
        }
        if (ret.size() == 0) {
            ret.add(java.net.Proxy.NO_PROXY);
        }
        return ret;
    }

    private static Proxy proxyFromHostPort(Proxy.Type type, String hostPortString) {
        try {
            String[] hostPort = hostPortString.split(":");
            String host = hostPort[0];
            int port = Integer.parseInt(hostPort[1]);
            return new Proxy(type, InetSocketAddress.createUnresolved(host, port));
        } catch (NumberFormatException|ArrayIndexOutOfBoundsException e) {
            Log.d(TAG, "Unable to parse proxy " + hostPortString + " " + e);
            return null;
        }
    }

    @Override
    public void connectFailed(URI uri, SocketAddress address, IOException failure) {

    }

}
