/*
 * Copyright 2007 nori090
 *
 * 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 org.coderepos.nori090.peercast.proxy;

import static org.coderepos.nori090.peercast.proxy.YpHttpProxy.HTTP_ELEMENT_CHARSET;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author nori090
 * @version $Rev: 136 $ $Date: 2008-07-27 20:23:03 +0900 (Sun, 27 Jul 2008) $
 */
public class YpRequest {

    private final static Pattern p1 = Pattern.compile( "^([^ ]+) http://([^ :/]+)(:([0-9]+))?([^ ]*) (HTTP/[0-9.]+)$" );

    private final static Pattern p2 = Pattern.compile( "^([^ ]+) /http://([^ :/]+)(:([0-9]+))?([^ ]*) (HTTP/[0-9.]+)$" );

    String host;

    String url;

    byte[] request;

    public YpRequest( InputStream in ) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        read( in, out );
        request = out.toByteArray();
    }

    private int read( InputStream in, OutputStream out ) {
        StringBuilder header = new StringBuilder( "" );
        String data = "";
        int byteCount = 0;
        int contentLength = 0;

        try {
            data = readLine( in );
            if ( data != null ) {
                StringBuilder host = new StringBuilder();
                StringBuilder url = new StringBuilder();
                Matcher m1 = p1.matcher( data );
                Matcher m2 = p2.matcher( data );
                if ( m1.find() ) {
                    host.append( m1.group( 2 ) );
                    url.append( "http://" ).append( m1.group( 2 ) );
                    if ( m1.group( 4 ) != null && !"".equals( m1.group( 4 ) ) ) {
                        host.append( ":" ).append( m1.group( 4 ) );
                        url.append( ":" ).append( m1.group( 4 ) );
                    }
                    if ( m1.group( 5 ) != null && !"".equals( m1.group( 5 ) ) ) {
                        url.append( m1.group( 5 ) );
                    }
                    else {
                        url.append( "/" );
                    }
                }
                else if ( m2.find() ) {
                    host.append( m2.group( 2 ) );
                    url.append( "http://" ).append( m2.group( 2 ) );
                    if ( m2.group( 4 ) != null && !"".equals( m2.group( 4 ) ) ) {
                        host.append( ":" ).append( m2.group( 4 ) );
                        url.append( ":" ).append( m2.group( 4 ) );
                    }
                    if ( m2.group( 5 ) != null && !"".equals( m2.group( 5 ) ) ) {
                        url.append( m2.group( 5 ) );
                    }
                    else {
                        url.append( "/" );
                    }
                }
                String hostname = host.toString();
                data = data.replaceFirst( "/http://" + hostname, "" );
                data = data.replaceFirst( "http://" + hostname, "" );
                header.append( data ).append( "\r\n" );
                this.host = host.toString();
                this.url = url.toString();
            }

            while ( ( data = readLine( in ) ) != null ) {
                if ( data.length() == 0 )
                    break;
                int pos = data.toLowerCase().indexOf( "host:" );
                if ( pos >= 0 ) {
                    data = "Host: " + host.toString();
                }
                header.append( data ).append( "\r\n" );
                pos = data.toLowerCase().indexOf( "content-length:" );
                if ( pos >= 0 )
                    contentLength = Integer.parseInt( data.substring( pos + 15 ).trim() );
            }

            header.append( "\r\n" );

            out.write( header.toString().getBytes( HTTP_ELEMENT_CHARSET ), 0, header.length() );

            if ( contentLength == 0 ) {
                out.flush();
                return header.length();
            }

            if ( contentLength > 0 ) {
                try {
                    byte[] buf = new byte[4096];
                    int bytesIn = 0;
                    while ( byteCount < contentLength && ( ( bytesIn = in.read( buf ) ) >= 0 ) ) {
                        out.write( buf, 0, bytesIn );
                        byteCount += bytesIn;
                    }
                }
                catch ( Exception e ) {
                    e.printStackTrace();
                }
            }
            out.flush();
        }
        catch ( Exception e ) {
            e.printStackTrace();
        }

        return ( header.length() + byteCount );
    }

    private String readLine( InputStream in ) {
        StringBuilder data = new StringBuilder( "" );

        try {
            in.mark( 1 );
            if ( in.read() == -1 ) {
                return null;
            }
            else {
                in.reset();
            }

            int c = -1;
            while ( ( c = in.read() ) >= 0 ) {
                if ( c == 0 || c == 10 || c == 13 ) {
                    break;
                }
                else {
                    data.append( (char) c );
                }
            }
            if ( c == 13 ) {
                in.mark( 1 );
                if ( in.read() != 10 ) {
                    in.reset();
                }
            }
        }
        catch ( Exception e ) {
            e.printStackTrace();
        }
        return data.toString();
    }
}
