/*
 *  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.apache.harmony.luni.internal.net.www.protocol.ftp;

import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketPermission;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.harmony.luni.internal.net.www.MimeTable;
import org.apache.harmony.luni.net.NetUtil;
import org.apache.harmony.luni.util.Msg;

public class FtpURLConnection extends URLConnection {

    private static final int FTP_PORT = 21;

    // FTP Reply Constants
    private static final int FTP_DATAOPEN = 125;

    private static final int FTP_OPENDATA = 150;

    private static final int FTP_OK = 200;

    private static final int FTP_USERREADY = 220;

    private static final int FTP_TRANSFEROK = 226;

    // private static final int FTP_PASV = 227;

    private static final int FTP_LOGGEDIN = 230;

    private static final int FTP_FILEOK = 250;

    private static final int FTP_PASWD = 331;

    // private static final int FTP_DATAERROR = 451;

    // private static final int FTP_ERROR = 500;

    private static final int FTP_NOTFOUND = 550;

    private Socket controlSocket;

    private Socket dataSocket;

    private ServerSocket acceptSocket;

    private InputStream ctrlInput;

    private InputStream inputStream;

    private OutputStream ctrlOutput;

    private int dataPort;

    private String username = "anonymous"; //$NON-NLS-1$

    private String password = ""; //$NON-NLS-1$

    private String replyCode;

    private String hostName;

    private Proxy proxy;

    private Proxy currentProxy;

    private URI uri;

    /**
     * FtpURLConnection constructor comment.
     * 
     * @param url
     */
    protected FtpURLConnection(URL url) {
        super(url);
        hostName = url.getHost();
        String parse = url.getUserInfo();
        if (parse != null) {
            int split = parse.indexOf(':');
            if (split >= 0) {
                username = parse.substring(0, split);
                password = parse.substring(split + 1);
            } else {
                username = parse;
            }
        }
        uri = null;
        try {
            uri = url.toURI();
        } catch (URISyntaxException e) {
            // do nothing.
        }
    }

    /**
     * FtpURLConnection constructor.
     * 
     * @param url
     * @param proxy
     */
    protected FtpURLConnection(URL url, Proxy proxy) {
        this(url);
        this.proxy = proxy;
    }

    /**
     * Change the server directory to that specified in the URL
     */
    private void cd() throws IOException {
        int idx = url.getFile().lastIndexOf('/');

        if (idx > 0) {
            String dir = url.getFile().substring(0, idx);
            write("CWD " + dir + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
            int reply = getReply();
            if (reply != FTP_FILEOK && dir.length() > 0 && dir.charAt(0) == '/') {
                write("CWD " + dir.substring(1) + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
                reply = getReply();
            }
            if (reply != FTP_FILEOK) {
                throw new IOException(Msg.getString("K0094")); //$NON-NLS-1$
            }
        }
    }

    /**
     * Establishes the connection to the resource specified by this
     * <code>URL</code>
     * 
     * @see #connected
     * @see java.io.IOException
     * @see URLStreamHandler
     */
    @Override
    public void connect() throws IOException {
        // Use system-wide ProxySelect to select proxy list,
        // then try to connect via elements in the proxy list.
        List<Proxy> proxyList = null;
        if (null != proxy) {
            proxyList = new ArrayList<Proxy>(1);
            proxyList.add(proxy);
        } else {
            proxyList = NetUtil.getProxyList(uri);
        }
        if (null == proxyList) {
            currentProxy = null;
            connectInternal();
        } else {
            ProxySelector selector = ProxySelector.getDefault();
            Iterator<Proxy> iter = proxyList.iterator();
            boolean connectOK = false;
            String failureReason = ""; //$NON-NLS-1$
            while (iter.hasNext() && !connectOK) {
                currentProxy = iter.next();
                try {
                    connectInternal();
                    connectOK = true;
                } catch (IOException ioe) {
                    failureReason = ioe.getLocalizedMessage();
                    // If connect failed, callback "connectFailed"
                    // should be invoked.
                    if (null != selector && Proxy.NO_PROXY != currentProxy) {
                        selector.connectFailed(uri, currentProxy.address(), ioe);
                    }
                }
            }
            if (!connectOK) {
                // K0097=Unable to connect to server\: {0}
                throw new IOException(Msg.getString("K0097", failureReason)); //$NON-NLS-1$
            }
        }
    }

    private void connectInternal() throws IOException {
        int port = url.getPort();
        int connectTimeout = getConnectTimeout();
        if (port <= 0) {
            port = FTP_PORT;
        }
        if (null == currentProxy || Proxy.Type.HTTP == currentProxy.type()) {
            controlSocket = new Socket();
        } else {
            controlSocket = new Socket(currentProxy);
        }
        InetSocketAddress addr = new InetSocketAddress(hostName, port);
        controlSocket.connect(addr, connectTimeout);
        connected = true;
        ctrlOutput = controlSocket.getOutputStream();
        ctrlInput = controlSocket.getInputStream();
        login();
        setType();
        if (!getDoInput()) {
            cd();
        }

        try {
            acceptSocket = new ServerSocket(0);
            dataPort = acceptSocket.getLocalPort();
            /* Cannot set REUSEADDR so we need to send a PORT command */
            port();
            if (connectTimeout == 0) {
                // set timeout rather than zero as before
                connectTimeout = 3000;
            }
            acceptSocket.setSoTimeout(getConnectTimeout());
            if (getDoInput()) {
                getFile();
            } else {
                sendFile();
            }
            dataSocket = acceptSocket.accept();
            dataSocket.setSoTimeout(getReadTimeout());
            acceptSocket.close();
        } catch (InterruptedIOException e) {
            throw new IOException(Msg.getString("K0095")); //$NON-NLS-1$
        }
        if (getDoInput()) {
            // BEGIN android-modified
            inputStream = new FtpURLInputStream(
                    new BufferedInputStream(dataSocket.getInputStream(), 8192),
                    controlSocket);
            // END android-modified
        }

    }

    /**
     * Returns the content type of the resource. Just takes a guess based on the
     * name.
     */
    @Override
    public String getContentType() {
        String result = guessContentTypeFromName(url.getFile());
        if (result == null) {
            return MimeTable.UNKNOWN;
        }
        return result;
    }

    private void getFile() throws IOException {
        int reply;
        String file = url.getFile();
        write("RETR " + file + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
        reply = getReply();
        if (reply == FTP_NOTFOUND && file.length() > 0 && file.charAt(0) == '/') {
            write("RETR " + file.substring(1) + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
            reply = getReply();
        }
        if (!(reply == FTP_OPENDATA || reply == FTP_TRANSFEROK)) {
            throw new FileNotFoundException(Msg.getString("K0096", reply)); //$NON-NLS-1$
        }
    }

    /**
     * Creates a input stream for writing to this URL Connection.
     * 
     * @return The input stream to write to
     * @throws IOException
     *             Cannot read from URL or error creating InputStream
     * 
     * @see #getContent()
     * @see #getOutputStream()
     * @see java.io.InputStream
     * @see java.io.IOException
     * 
     */
    @Override
    public InputStream getInputStream() throws IOException {
        if (!connected) {
            connect();
        }
        return inputStream;
    }

    /**
     * Returns the permission object (in this case, SocketPermission) with the
     * host and the port number as the target name and "resolve, connect" as the
     * action list.
     * 
     * @return the permission object required for this connection
     * @throws IOException
     *             thrown when an IO exception occurs during the creation of the
     *             permission object.
     */
    @Override
    public Permission getPermission() throws IOException {
        int port = url.getPort();
        if (port <= 0) {
            port = FTP_PORT;
        }
        return new SocketPermission(hostName + ":" + port, "connect, resolve"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    /**
     * Creates a output stream for writing to this URL Connection.
     * 
     * @return The output stream to write to
     * @throws IOException
     *             when the OutputStream could not be created
     * 
     * @see #getContent()
     * @see #getInputStream()
     * @see java.io.IOException
     * 
     */

    @Override
    public OutputStream getOutputStream() throws IOException {
        if (!connected) {
            connect();
        }
        return dataSocket.getOutputStream();
    }

    private int getReply() throws IOException {
        byte[] code = new byte[3];
        ctrlInput.read(code, 0, code.length);
        replyCode = new String(code, "ISO8859_1"); //$NON-NLS-1$
        boolean multiline = false;
        if (ctrlInput.read() == '-') {
            multiline = true;
        }
        readLine(); /* Skip the rest of the first line */
        if (multiline) {
            while (readMultiLine()) {/* Read all of a multiline reply */
            }
        }
        return Integer.parseInt(new String(code, "ISO8859_1")); //$NON-NLS-1$
    }

    private void login() throws IOException {
        int reply;
        reply = getReply();
        if (reply == FTP_USERREADY) {
        } else {
            throw new IOException(Msg.getString("K0097", url.getHost())); //$NON-NLS-1$
        }
        write("USER " + username + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
        reply = getReply();
        if (reply == FTP_PASWD || reply == FTP_LOGGEDIN) {
        } else {
            throw new IOException(Msg.getString("K0098", url.getHost())); //$NON-NLS-1$
        }
        if (reply == FTP_PASWD) {
            write("PASS " + password + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
            reply = getReply();
            if (!(reply == FTP_OK || reply == FTP_USERREADY || reply == FTP_LOGGEDIN)) {
                throw new IOException(Msg.getString("K0098", url.getHost())); //$NON-NLS-1$
            }
        }
    }

    private void port() throws IOException {
        write("PORT " //$NON-NLS-1$
                + controlSocket.getLocalAddress().getHostAddress().replace('.',
                        ',') + ',' + (dataPort >> 8) + ','
                + (dataPort & 255)
                + "\r\n"); //$NON-NLS-1$
        if (getReply() != FTP_OK) {
            throw new IOException(Msg.getString("K0099")); //$NON-NLS-1$
        }
    }

    /**
     * Read a line of text and return it for possible parsing
     */
    private String readLine() throws IOException {
        StringBuffer sb = new StringBuffer();
        int c;
        while ((c = ctrlInput.read()) != '\n') {
            sb.append((char) c);
        }
        return sb.toString();
    }

    private boolean readMultiLine() throws IOException {
        String line = readLine();
        if (line.length() < 4) {
            return true;
        }
        if (line.substring(0, 3).equals(replyCode)
                && (line.charAt(3) == (char) 32)) {
            return false;
        }
        return true;
    }

    /**
     * Issue the STOR command to the server with the file as the parameter
     */
    private void sendFile() throws IOException {
        int reply;
        write("STOR " //$NON-NLS-1$
                + url.getFile().substring(url.getFile().lastIndexOf('/') + 1,
                        url.getFile().length()) + "\r\n"); //$NON-NLS-1$
        reply = getReply();
        if (!(reply == FTP_OPENDATA || reply == FTP_OK || reply == FTP_DATAOPEN)) {
            throw new IOException(Msg.getString("K009a")); //$NON-NLS-1$
        }
    }

    /**
     * Set the flag if this <code>URLConnection</code> supports input (read).
     * It cannot be set after the connection is made. FtpURLConnections cannot
     * support both input and output
     * 
     * @param newValue *
     * @throws IllegalAccessError
     *             when this method attempts to change the flag after connected
     * 
     * @see #doInput
     * @see #getDoInput()
     * @see java.lang.IllegalAccessError
     * @see #setDoInput(boolean)
     */
    @Override
    public void setDoInput(boolean newValue) {
        if (connected) {
            throw new IllegalAccessError();
        }
        this.doInput = newValue;
        this.doOutput = !newValue;
    }

    /**
     * Set the flag if this <code>URLConnection</code> supports output(read).
     * It cannot be set after the connection is made.\ FtpURLConnections cannot
     * support both input and output.
     * 
     * @param newValue
     * 
     * @throws IllegalAccessError
     *             when this method attempts to change the flag after connected
     * 
     * @see #doOutput
     * @see java.lang.IllegalAccessError
     * @see #setDoOutput(boolean)
     */
    @Override
    public void setDoOutput(boolean newValue) {
        if (connected) {
            throw new IllegalAccessError();
        }
        this.doOutput = newValue;
        this.doInput = !newValue;
    }

    /**
     * Set the type of the file transfer. Only Image is supported
     */
    private void setType() throws IOException {
        write("TYPE I\r\n"); //$NON-NLS-1$
        if (getReply() != FTP_OK) {
            throw new IOException(Msg.getString("K009b")); //$NON-NLS-1$
        }
    }

    private void write(String command) throws IOException {
        ctrlOutput.write(command.getBytes("ISO8859_1")); //$NON-NLS-1$
    }
}
