package client;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.Vector;
import javax.media.*;
import javax.media.control.*;
import javax.media.format.*;
import javax.media.protocol.*;
import javax.swing.*;
import java.net.*;

public class VideoSender extends JFrame implements ControllerListener, Runnable
{
	Player player = null;
	Processor p = null;
	DataSource videoSource = null;
	MediaLocator videoLoc = null;
	DataSink filewriter = null;
	VTransmit at = null;
	Container c;
	JPanel recPanel;
	JButton rec, stopRec;
	String ip;
	String port;
	
//	public MediaSender( String IP, String port )
//	{
//		super( "視訊" );
//		ip = IP;
//		this.port = port;
//		
////		captureVideo();
////		playFile( "file:///C:/XD.avi" );
////		sendVideo();
//		
//		addWindowListener(
//				new WindowAdapter(){
//						public void windowClosing( WindowEvent e ){
//							if( p != null )
//								p.close();
////							if( videoSource != null )
////								videoSource.disconnect();
//							if( player != null )
//								player.close();
//							at.stoptransmit();
//							setVisible( false );
//						}
//				}
//		);
//	}
	
	public VideoSender()
	{
		super( "視訊" );
		
		c = getContentPane();
		c.setLayout( new BorderLayout() );
		rec = new JButton( "錄影" );
		rec.addActionListener(
				new ActionListener(){
					public void actionPerformed( ActionEvent e ){
						rec.setEnabled( false );
						stopRec.setEnabled( true );
						recordVideo();
					}
		});
		stopRec = new JButton( "停止" );
		stopRec.addActionListener(
				new ActionListener(){
					public void actionPerformed( ActionEvent e ){
						rec.setEnabled( true );
						stopRec.setEnabled( false );
						if( p != null )
						{
							p.stop();
							p.close();
						}
						if( filewriter != null )
						{
							try {
								filewriter.stop();
							} catch ( IOException e1 ) {
								e1.printStackTrace();
							}
							filewriter.close();
						}
					}
		});
		recPanel = new JPanel();
		recPanel.setLayout( new GridLayout( 2, 1 ) );
		recPanel.add( rec );
		recPanel.add( stopRec );
		stopRec.setEnabled( false );
		c.add( recPanel, BorderLayout.EAST );
		
//		captureVideo();
//		playFile( "file:///C:/XD.avi" );
//		sendVideo();
		
		addWindowListener(
				new WindowAdapter(){
						public void windowClosing( WindowEvent e ){
							if( p != null )
								p.close();
//							if( videoSource != null )
//								videoSource.disconnect();
							if( player != null )
								player.close();
							at.stoptransmit();
							setVisible( false );
						}
				}
		);
	}
	
	public boolean initialize()
	{
		Vector deviceList = CaptureDeviceManager.getDeviceList( null );
		CaptureDeviceInfo di = null;
		Format format[];

		for( int i = 0; videoLoc == null && i < deviceList.size(); i++ )
		{
			di = ( CaptureDeviceInfo )deviceList.get( i );
//			System.out.println( di.getName() + " " + di.getFormats() );
			format = di.getFormats();
			for( int j = 0; j < format.length; j++ )
				if( format[ j ] instanceof VideoFormat )
				{
//					System.out.println( "Video: " + di.getName() );
					videoLoc = di.getLocator();
					break;
				}
		}
		
//		videoLoc = new MediaLocator( "file:///C:/bon.mpg" );
		
		if( videoLoc == null )
		{
			JOptionPane.showMessageDialog( null, "找不到網路攝影機！");
			return false;
		}
		try {
			DataSource ds = Manager.createDataSource( videoLoc );
			videoSource = Manager.createCloneableDataSource( ds );
		} catch ( NoDataSourceException e ) {
//			e.printStackTrace();
		} catch ( IOException e ) {
//			e.printStackTrace();
		}
		if( videoSource != null )
			return true;
		else
		{
			JOptionPane.showMessageDialog( null, "找不到網路攝影機！" );
			return false;
		}
	}
	
	public void startPlayer()
	{
		Component comp;
		
		player.start();
//		p.realize();
//		p.start();
		
		if(( comp = player.getVisualComponent()) != null )
			c.add( comp, BorderLayout.CENTER );
		if(( comp = player.getControlPanelComponent()) != null )
			c.add( comp, BorderLayout.SOUTH );
//		if(( comp = p.getVisualComponent()) != null )
//			c.add( comp, BorderLayout.CENTER );
//		if(( comp = p.getControlPanelComponent()) != null )
//			c.add( comp, BorderLayout.SOUTH );
		validate();
		//		c.add( stopRec, BorderLayout.EAST );
		pack();
		setVisible( true );
	}
	
	public void stop()
	{
		player.stop();
		player.deallocate();
	}
	
	public void destroy()
	{
		player.close();
	}
	
	public synchronized void controllerUpdate( ControllerEvent event )
	{
		Container c = getContentPane();
		if( event instanceof RealizeCompleteEvent )
		{
			Component comp;
			if(( comp = player.getVisualComponent()) != null )
				c.add( "center", comp );
			if(( comp = player.getControlPanelComponent()) != null )
				c.add( "South", comp );
			validate();
		}	
	}
	
	public void set( String ip, String port )
	{
		this.ip = ip;
		this.port = port;
	}
	
//	public void captureVideo( String source )
//	public void captureVideo()
	
	public void run()
	{
//		CaptureDeviceInfo di = CaptureDeviceManager.getDevice( source );
//		videoLoc = new MediaLocator( "file:///C:/XD.avi" );
//		if( videoLoc == null )
//		{
//			JOptionPane.showMessageDialog( null, "５３找不到網路攝影機！");
//			return;
//		}
		
		try {
//			videoSource = Manager.createCloneableDataSource(
//					Manager.createDataSource( videoLoc ) );
//			videoSource = Manager.createDataSource( videoLoc );
			player = Manager.createRealizedPlayer( videoSource );
//			System.out.println( "datasource" );
//			p = Manager.createProcessor( videoSource );
//			p.configure();
//			p.setContentDescriptor( new ContentDescriptor(ContentDescriptor.RAW));
			System.out.println( "Successfully construct" );
			startPlayer();
			
			at = new VTransmit( videoSource, ip, port, null );
			at.start();
//			sendVideo();
//			recordVideo();
			
		} catch ( NoPlayerException e ){
			e.printStackTrace();
		} catch ( IOException e ){
			e.printStackTrace();
//		} catch (NoDataSourceException e){
//			e.printStackTrace();
		} catch ( CannotRealizeException e ){
			e.printStackTrace();
		}
	}
	
	public void recordVideo()
	{
		DataSource ds = ( ( SourceCloneable )videoSource ).createClone();
		try {
			p = Manager.createProcessor( ds );
			FileTypeDescriptor type = new FileTypeDescriptor(
					FileTypeDescriptor.MSVIDEO );
			MediaLocator dest = new MediaLocator( "file:///C:/foo.avi" );

			p.configure();
			
			while( p.getState() != Processor.Configured );

			p.setContentDescriptor( type );
			p.realize();
			
			while( p.getState() != Processor.Realized );

			p.start();
			filewriter = Manager.createDataSink( p.getDataOutput(), dest );
			filewriter.open();
			filewriter.start();
			
		} catch ( NoProcessorException e ){
			e.printStackTrace();
		} catch ( IOException e ){
			e.printStackTrace();
		} catch ( NoDataSinkException e ){
			e.printStackTrace();
		}
	}
	
	public void sendVideo()
	{
		DataSource ds = ( ( SourceCloneable )videoSource ).createClone();
//		MediaLocator loc = new MediaLocator( "file:///C:/XD.avi" );
//		DataSource ds = null;
//		try {
//			ds = Manager.createDataSource( loc );
//		} catch (NoDataSourceException e1) {
//			e1.printStackTrace();
//		} catch (IOException e1) {
//			e1.printStackTrace();
//		}
		try {
			p = Manager.createProcessor( ds );
			p.configure();
			while( p.getState() != Processor.Configured );
			p.setContentDescriptor(
					new ContentDescriptor( ContentDescriptor.RAW ));
			TrackControl track[] = p.getTrackControls();
			boolean encodingOK = false;
			
			for( int i = 0; i < track.length; i++ )
			{
				System.out.println( track[i].toString() );
				if( !encodingOK && track[i] instanceof FormatControl )
				{
					if( ( ( FormatControl )track[i] ).setFormat(
							new VideoFormat(VideoFormat.H263_RTP ) ) == null )
							track[i].setEnabled( false );
					else
						encodingOK = true;
				}
				else
					track[i].setEnabled( false );
			}
			if( !encodingOK )
			{
				System.out.println( "Encoding failed" );
				return;
			}
			p.realize();
			MediaLocator dest = new MediaLocator(
					"rtp://140.112.18.208:48150/video" );
			while( p.getState() != Processor.Realized );
			DataSource output = p.getDataOutput();
			DataSink sink = Manager.createDataSink( output, dest );
			sink.open();
			System.out.println( "Transmitting..." );
			sink.start();
			output.start();
			
		} catch ( NoProcessorException e ){
			e.printStackTrace();
		} catch ( IOException e ){
			e.printStackTrace();
		} catch ( NoDataSinkException e ){
			e.printStackTrace();
		} catch ( NotRealizedError e ){
			e.printStackTrace();
		}
	}
}
