using System;
using System.IO;
using System.Text;
using Npgsql;

namespace pgcopyNamespace {

    class pgcopy {

        static bool verbose = false;

        public static void Main(string[] args) {
            if( args.Length < 1 )
            {
                Console.Out.WriteLine("Usage: pgcopy [-v] [-c connString] {-i infile|-o outfile|SQL} ...");
                Console.Out.WriteLine("Eg. 'CREATE TABLE t(t text)' -i pgcopy.cs 'COPY t FROM STDIN' 'COPY t TO STDOUT'");
                return;
            }
            try
            {
                runCopy(args);
            }
            catch( Exception e )
            {
                Console.Out.WriteLine("Copy failed: " + e);
            }
        }

        private static void runCopy(string[] args) {
            string connString = 
                "Server=127.0.0.1;Port=5432;User Id=test;Password=password;Database=test;";
            int i = 0;
            if(args.Length > 1 && args[0] == "-c")
            {
                connString = args[1];
                i = 2;
            }
            if(verbose) Console.Out.WriteLine("Create connection: " + connString);
            Npgsql.NpgsqlConnection con = new Npgsql.NpgsqlConnection(connString);
            con.Open();
            FileStream ifs = null, ofs = null;
            while( i < args.Length )
            {
                if( args[i] == "-i" )
                {
                    ifs = args[++i] == "-" ? null : new FileStream( args[i], FileMode.Open, FileAccess.Read );
                    ++i;
                }
                else if( args[i] == "-o" )
                {
                    ofs = args[++i] == "-" ? null : new FileStream( args[i], FileMode.OpenOrCreate, FileAccess.Write );
                    ++i;
                }
                else
                {
                    runCmd(args[i++], con, ifs, ofs);
                }
            }
        }

        private static void runCmd(string queryString, NpgsqlConnection con, FileStream ifs, FileStream ofs)
        {
            if(verbose) Console.Out.WriteLine("Create Command: " + queryString);
            NpgsqlCommand cmd = new NpgsqlCommand(queryString, con);

            if( cmd.CommandText.Contains(" FROM STDIN") )
            {
                if(verbose) Console.Out.WriteLine("Copy In");
                NpgsqlCopyIn copyIn = new NpgsqlCopyIn(cmd, con, ifs);
                copyIn.Start();
                if( copyIn.IsActive ) // streaming, not single-pass
                {
                    String row;
                    System.Text.Encoding encoding = new System.Text.UTF8Encoding();
                    while( (row = Console.In.ReadLine()) != null )
                    {
                        if(verbose) Console.Out.WriteLine("Sending row: '" + row + "'");
                        byte[] buf = encoding.GetBytes(row + '\n');
                        copyIn.CopyStream.Write(buf, 0, buf.Length);
                    }
                    copyIn.End();
                }
            }
            else if( cmd.CommandText.Contains(" TO STDOUT") )
            {
                if(verbose) Console.Out.WriteLine("Copy Out");
                NpgsqlCopyOut copyOut = new NpgsqlCopyOut(cmd, con, ofs);
                copyOut.Start();
                if( copyOut.IsActive ) // streaming, not single-pass
                {
                    byte[] buf;
                    while( (buf = copyOut.Read) != null )
                    {
                        Console.Out.Write(System.Text.Encoding.ASCII.GetString(buf));
                    }
                    copyOut.End();
                } 
            }
            else
            {
                if(verbose) Console.Out.WriteLine("Non-Copy query");
                cmd.ExecuteNonQuery();
            }
            if(verbose) Console.Out.WriteLine("Done " + queryString);
        }
    }
}