/*
 * DCCSendClient.java
 * IRCCore
 *
 * Created by tarchan on 2007/01/21.
 * Copyright (c) 2007 tarchan. All rights reserved.
 */
package com.mac.tarchan.irc.dcc;

import java.awt.Toolkit;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.MappedByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

import com.mac.tarchan.irc.IRCMessage;

/**
 * DCCSendClient
 * 
 * @author tarchan
 */
public class DCCSendClient
    implements Runnable {
    private String nick;

    private String hostname;

    private int port;

    private String filename;

    private long filesize;

    public DCCSendClient( IRCMessage source, String command ) {
        String[] args = command.split( " " );
        if ( args.length < 6 )
            throw new IllegalArgumentException( command );

        nick = source.getNick();
        filename = args[2];
        hostname = args[3];
        port = Integer.parseInt( args[4] );
        filesize = Long.parseLong( args[5] );
        InetSocketAddress inet = new InetSocketAddress( hostname, port );
        System.out.format( "DCC SEND=%s,%s,%s,%s(%d)\n", nick, Arrays.asList( args ), inet, filename, filesize );
    }

    public void save() {
        saveAs( filename );
    }

    public void saveAs( String path ) {
        this.filepath = path;
        run();
        // new Thread(this).start();
    }

    private String filepath;

    private IOException ioException;

    public void run() {
        try {
            receive();
            Toolkit.getDefaultToolkit().beep();
        }
        catch ( IOException x ) {
            ioException = x;
            x.printStackTrace();
        }
    }

    public IOException getIOException() {
        return ioException;
    }

    private void receive()
        throws IOException {
        InetSocketAddress inet = new InetSocketAddress( hostname, port );
        SocketChannel source = SocketChannel.open( inet );
        // BufferedInputStream read = new
        // BufferedInputStream(Channels.newInputStream(sch));
        BufferedOutputStream reply = new BufferedOutputStream( Channels.newOutputStream( source ) );

        // Socket socket = new Socket();
        // socket.setSoTimeout(60 * 1000);
        // socket.connect(inet);
        System.out.println( "channel=" + source );
        File file = new File( filepath );
        FileChannel target = new FileOutputStream( file ).getChannel();
        System.out.println( "file=" + file.getAbsolutePath() + "," + target + "," + file.length() );
        // ByteBuffer mem = ByteBuffer.allocate(file.length());
        MappedByteBuffer mem = target.map( FileChannel.MapMode.READ_WRITE, 0, filesize );
        ByteBuffer ack = ByteBuffer.allocate( 4 ).order( ByteOrder.BIG_ENDIAN );
        for ( long pos = target.position(); pos < filesize; ) {
            // long count = filesize - pos;
            // count = Math.min(count, Integer.MAX_VALUE);
            // long transSize = fch.transferFrom(sch, pos, count);
            long transSize = source.read( mem );
            System.out.println( "trans=" + pos + "+" + transSize );
            pos += transSize;

            // ACK、読み込み済みのサイズを返す。
            ack.putInt( (int) pos );
            reply.write( ack.array() );
            reply.flush();
        }

        // read.close();
        // send.close();
        // channel.socket().close();
        source.close();
        target.close();
    }
}
