(*
 * 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.
 *)

unit TestServer;

interface

uses
  SysUtils,
  Generics.Collections,
  Thrift.Console,
  Thrift.Server,
  Thrift.Transport,
  Thrift.Collections,
  Thrift.Utils,
  Thrift.Test,
  Thrift,
  Contnrs;

type
  TTestServer = class
  public
    type

      ITestHandler = interface( TThriftTest.Iface )
        procedure SetServer( AServer : IServer );
      end;

      TTestHandlerImpl = class( TInterfacedObject, ITestHandler )
      private
        FServer : IServer;
      protected
        procedure testVoid();
        function testString(thing: string): string;
        function testByte(thing: ShortInt): ShortInt;
        function testI32(thing: Integer): Integer;
        function testI64(thing: Int64): Int64;
        function testDouble(thing: Double): Double;
        function testStruct(thing: IXtruct): IXtruct;
        function testNest(thing: IXtruct2): IXtruct2;
        function testMap(thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>;
        function testStringMap(thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>;
        function testSet(thing: IHashSet<Integer>): IHashSet<Integer>;
        function testList(thing: IThriftList<Integer>): IThriftList<Integer>;
        function testEnum(thing: TNumberz): TNumberz;
        function testTypedef(thing: Int64): Int64;
        function testMapMap(hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
        function testInsanity(argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
        function testMulti(arg0: ShortInt; arg1: Integer; arg2: Int64; arg3: IThriftDictionary<SmallInt, string>; arg4: TNumberz; arg5: Int64): IXtruct;
        procedure testException(arg: string);
        function testMultiException(arg0: string; arg1: string): IXtruct;
        procedure testOneway(secondsToSleep: Integer);

         procedure testStop;

        procedure SetServer( AServer : IServer );
      end;

      class procedure Execute( args: array of string);
  end;

implementation

{ TTestServer.TTestHandlerImpl }

procedure TTestServer.TTestHandlerImpl.SetServer(AServer: IServer);
begin
  FServer := AServer;
end;

function TTestServer.TTestHandlerImpl.testByte(thing: ShortInt): ShortInt;
begin
	Console.WriteLine('testByte("' + IntToStr( thing) + '")');
	Result := thing;
end;

function TTestServer.TTestHandlerImpl.testDouble(thing: Double): Double;
begin
	Console.WriteLine('testDouble("' + FloatToStr( thing ) + '")');
	Result := thing;
end;

function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz;
begin
	Console.WriteLine('testEnum(' + IntToStr( Integer( thing)) + ')');
  Result := thing;
end;

procedure TTestServer.TTestHandlerImpl.testException(arg: string);
var
  x : TXception;
begin
  Console.WriteLine('testException(' + arg + ')');
  if ( arg = 'Xception') then
  begin
    x := TXception.Create;
    x.ErrorCode := 1001;
    x.Message_ := 'This is an Xception';
    raise x;
  end;
end;

function TTestServer.TTestHandlerImpl.testI32(thing: Integer): Integer;
begin
	Console.WriteLine('testI32("' + IntToStr( thing) + '")');
	Result := thing;
end;

function TTestServer.TTestHandlerImpl.testI64(thing: Int64): Int64;
begin
	Console.WriteLine('testI64("' + IntToStr( thing) + '")');
	Result := thing;
end;

function TTestServer.TTestHandlerImpl.testInsanity(
  argument: IInsanity): IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;
var
  hello, goodbye : IXtruct;
  crazy : IInsanity;
  looney : IInsanity;
  first_map : IThriftDictionary<TNumberz, IInsanity>;
  second_map : IThriftDictionary<TNumberz, IInsanity>;
  insane : IThriftDictionary<Int64, IThriftDictionary<TNumberz, IInsanity>>;

begin

  Console.WriteLine('testInsanity()');
  hello := TXtructImpl.Create;
  hello.String_thing := 'hello';
  hello.Byte_thing := 2;
  hello.I32_thing := 2;
  hello.I64_thing := 2;

  goodbye := TXtructImpl.Create;
  goodbye.String_thing := 'Goodbye4';
  goodbye.Byte_thing := 4;
  goodbye.I32_thing := 4;
  goodbye.I64_thing := 4;

  crazy := TInsanityImpl.Create;
	crazy.UserMap := TThriftDictionaryImpl<TNumberz, Int64>.Create;
	crazy.UserMap.AddOrSetValue( TNumberz.EIGHT, 8);
	crazy.Xtructs := TThriftListImpl<IXtruct>.Create;
	crazy.Xtructs.Add(goodbye);

  looney := TInsanityImpl.Create;
  crazy.UserMap.AddOrSetValue( TNumberz.FIVE, 5);
	crazy.Xtructs.Add(hello);

  first_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;
  second_map := TThriftDictionaryImpl<TNumberz, IInsanity>.Create;

  first_map.AddOrSetValue( TNumberz.SIX, crazy);
  first_map.AddOrSetValue( TNumberz.THREE, crazy);

  second_map.AddOrSetValue( TNumberz.SIX, looney);

  insane := TThriftDictionaryImpl<Int64, IThriftDictionary<TNumberz, IInsanity>>.Create;

  insane.AddOrSetValue( 1, first_map);
  insane.AddOrSetValue( 2, second_map);

  Result := insane;
end;

function TTestServer.TTestHandlerImpl.testList(
  thing: IThriftList<Integer>): IThriftList<Integer>;
var
  first : Boolean;
  elem : Integer;
begin
  Console.Write('testList({');
  first := True;
  for elem in thing do
  begin
    if first then
    begin
      first := False;
    end else
    begin
      Console.Write(', ');
    end;
    Console.Write( IntToStr( elem));
  end;
  Console.WriteLine('})');
  Result := thing;
end;

function TTestServer.TTestHandlerImpl.testMap(
  thing: IThriftDictionary<Integer, Integer>): IThriftDictionary<Integer, Integer>;
var
  first : Boolean;
  key : Integer;
begin
  Console.Write('testMap({');
  first := True;
  for key in thing.Keys do
  begin
  	if (first) then
    begin
      first := false;
    end else
    begin
      Console.Write(', ');
    end;
    Console.Write(IntToStr(key) + ' => ' + IntToStr( thing[key]));
  end;
	Console.WriteLine('})');
  Result := thing;
end;

function TTestServer.TTestHandlerImpl.TestMapMap(
  hello: Integer): IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
var
  mapmap : IThriftDictionary<Integer, IThriftDictionary<Integer, Integer>>;
  pos : IThriftDictionary<Integer, Integer>;
  neg : IThriftDictionary<Integer, Integer>;
  i : Integer;
begin
  Console.WriteLine('testMapMap(' + IntToStr( hello) + ')');
  mapmap := TThriftDictionaryImpl<Integer, IThriftDictionary<Integer, Integer>>.Create;
  pos := TThriftDictionaryImpl<Integer, Integer>.Create;
  neg := TThriftDictionaryImpl<Integer, Integer>.Create;

  for i := 1 to 4 do
  begin
    pos.AddOrSetValue( i, i);
    neg.AddOrSetValue( -i, -i);
  end;

  mapmap.AddOrSetValue(4, pos);
  mapmap.AddOrSetValue( -4, neg);

  Result := mapmap;
end;

function TTestServer.TTestHandlerImpl.testMulti(arg0: ShortInt; arg1: Integer;
  arg2: Int64; arg3: IThriftDictionary<SmallInt, string>; arg4: TNumberz;
  arg5: Int64): IXtruct;
var
  hello : IXtruct;
begin
  Console.WriteLine('testMulti()');
  hello := TXtructImpl.Create;
  hello.String_thing := 'Hello2';
  hello.Byte_thing := arg0;
  hello.I32_thing := arg1;
  hello.I64_thing := arg2;
  Result := hello;
end;

function TTestServer.TTestHandlerImpl.testMultiException(arg0,
  arg1: string): IXtruct;
var
  x : TXception;
  x2 : TXception2;
begin
  Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')');
  if ( arg0 = 'Xception') then
  begin
    x := TXception.Create;
    x.ErrorCode := 1001;
    x.Message := 'This is an Xception';
    raise x;
  end else
  if ( arg0 = 'Xception2') then
  begin
    x2 := TXception2.Create;
    x2.ErrorCode := 2002;
    x2.Struct_thing := TXtructImpl.Create;
    x2.Struct_thing.String_thing := 'This is an Xception2';
    raise x2;
  end;

  Result := TXtructImpl.Create;
  Result.String_thing := arg1;
end;

function TTestServer.TTestHandlerImpl.testNest(thing: IXtruct2): IXtruct2;
var
  temp : IXtruct;
begin
  temp := thing.Struct_thing;
	Console.WriteLine('testNest({' +
				 IntToStr( thing.Byte_thing) + ', {' +
				 '"' + temp.String_thing + '", ' +
				 IntToStr( temp.Byte_thing) + ', ' +
				 IntToStr( temp.I32_thing) + ', ' +
				 IntToStr( temp.I64_thing) + '}, ' +
				 IntToStr( temp.I32_thing) + '})');
  Result := thing;
end;

procedure TTestServer.TTestHandlerImpl.testOneway(secondsToSleep: Integer);
begin
	Console.WriteLine('testOneway(' + IntToStr( secondsToSleep )+ '), sleeping...');
	Sleep(secondsToSleep * 1000);
	Console.WriteLine('testOneway finished');
end;

function TTestServer.TTestHandlerImpl.testSet(
  thing: IHashSet<Integer>):IHashSet<Integer>;
var
  first : Boolean;
  elem : Integer;
begin
  Console.Write('testSet({');
  first := True;

  for elem in thing do
  begin
    if first then
    begin
      first := False;
    end else
    begin
      Console.Write( ', ');
    end;
    Console.Write( IntToStr( elem));
  end;
  Console.WriteLine('})');
  Result := thing;
end;

procedure TTestServer.TTestHandlerImpl.testStop;
begin
  if FServer <> nil then
  begin
    FServer.Stop;
  end;
end;

function TTestServer.TTestHandlerImpl.testString(thing: string): string;
begin
	Console.WriteLine('teststring("' + thing + '")');
	Result := thing;
end;

function TTestServer.TTestHandlerImpl.testStringMap(
  thing: IThriftDictionary<string, string>): IThriftDictionary<string, string>;
begin

end;

function TTestServer.TTestHandlerImpl.testTypedef(thing: Int64): Int64;
begin
	Console.WriteLine('testTypedef(' + IntToStr( thing) + ')');
  Result := thing;
end;

procedure TTestServer.TTestHandlerImpl.TestVoid;
begin
  Console.WriteLine('testVoid()');
end;

function TTestServer.TTestHandlerImpl.testStruct(thing: IXtruct): IXtruct;
begin
  Console.WriteLine('testStruct({' +
    '"' + thing.String_thing + '", ' +
		  IntToStr( thing.Byte_thing) + ', ' +
			IntToStr( thing.I32_thing) + ', ' +
			IntToStr( thing.I64_thing));
  Result := thing;
end;

{ TTestServer }

class procedure TTestServer.Execute(args: array of string);
var
  UseBufferedSockets : Boolean;
  UseFramed : Boolean;
  Port : Integer;
  testHandler : ITestHandler;
  testProcessor : IProcessor;
  ServerSocket : IServerTransport;
  ServerEngine : IServer;
  TransportFactroy : ITransportFactory;


begin
  try
    UseBufferedSockets := False;
    UseFramed := False;
    Port := 9090;

    if ( Length( args) > 0) then
    begin
      Port :=  StrToIntDef( args[0], Port);

      if ( Length( args) > 0) then
      begin
        if ( args[0] = 'raw' ) then
        begin
          // as default
        end else
        if ( args[0] = 'buffered' ) then
        begin
          UseBufferedSockets := True;
        end else
        if ( args[0] = 'framed' ) then
        begin
          UseFramed := True;
        end else
        begin
          // Fall back to the older boolean syntax
          UseBufferedSockets := StrToBoolDef( args[1], UseBufferedSockets);
        end
      end
    end;

    testHandler := TTestHandlerImpl.Create;

    testProcessor := TThriftTest.TProcessorImpl.Create( testHandler );
    ServerSocket := TServerSocketImpl.Create( Port, 0, UseBufferedSockets );
    if UseFramed then
    begin
      TransportFactroy := TFramedTransportImpl.TFactory.Create;
      ServerEngine := TSimpleServer.Create( testProcessor, ServerSocket,
         TransportFactroy);
    end else
    begin
      ServerEngine := TSimpleServer.Create( testProcessor, ServerSocket);
    end;

    testHandler.SetServer( ServerEngine);

    Console.WriteLine('Starting the server on port ' + IntToStr( Port) +
      IfValue(UseBufferedSockets, ' with buffered socket', '') +
      IfValue(useFramed, ' with framed transport', '') +
      '...');

    serverEngine.Serve;
    testHandler.SetServer( nil);

  except
    on E: Exception do
    begin
      Console.Write( E.Message);
    end;
  end;
  Console.WriteLine( 'done.');
end;

end.
