import 'dart:async';
import 'package:proto_socket/proto_socket.dart';

import 'package:alt_client/src/contracts/alt_contracts.dart';
import 'package:alt_client/src/generated/alt/v1/backtest.pb.dart';
import 'package:alt_client/src/generated/alt/v1/common.pb.dart';
import 'package:alt_client/src/generated/alt/v1/market.pb.dart';
import 'socket_endpoint.dart';

class AltSocketClient extends WsProtobufClient {
  AltSocketClient(
    dynamic ws, {
    int heartbeatIntervalTime = 30,
    int heartbeatWaitTime = 10,
  }) : super(ws, heartbeatIntervalTime, heartbeatWaitTime, altParserMap());

  static Future<AltSocketClient> connect(
    AltSocketEndpoint endpoint, {
    int heartbeatIntervalTime = 30,
    int heartbeatWaitTime = 10,
  }) async {
    final ws = await WsProtobufClient.connect(
      endpoint.host,
      endpoint.port,
      path: endpoint.path,
    );
    return AltSocketClient(
      ws,
      heartbeatIntervalTime: heartbeatIntervalTime,
      heartbeatWaitTime: heartbeatWaitTime,
    );
  }

  Future<HelloResponse> hello({Duration timeout = const Duration(seconds: 2)}) {
    return sendRequest<HelloRequest, HelloResponse>(
      HelloRequest()
        ..clientName = 'alt-client'
        ..clientVersion = 'dev'
        ..altProtocolVersion = 'alt.v1',
      timeout: timeout,
    );
  }

  Future<ListBacktestRunsResponse> listBacktestRuns(
    ListBacktestRunsRequest request, {
    Duration timeout = const Duration(seconds: 2),
  }) {
    return sendRequest<ListBacktestRunsRequest, ListBacktestRunsResponse>(
      request,
      timeout: timeout,
    );
  }

  Future<GetBacktestRunDetailResponse> getBacktestRunDetail(
    GetBacktestRunDetailRequest request, {
    Duration timeout = const Duration(seconds: 2),
  }) {
    return sendRequest<GetBacktestRunDetailRequest,
        GetBacktestRunDetailResponse>(
      request,
      timeout: timeout,
    );
  }

  Future<GetBacktestResultResponse> getBacktestResult(
    GetBacktestResultRequest request, {
    Duration timeout = const Duration(seconds: 2),
  }) {
    return sendRequest<GetBacktestResultRequest, GetBacktestResultResponse>(
      request,
      timeout: timeout,
    );
  }

  Future<CompareBacktestRunsResponse> compareBacktestRuns(
    CompareBacktestRunsRequest request, {
    Duration timeout = const Duration(seconds: 2),
  }) {
    return sendRequest<CompareBacktestRunsRequest, CompareBacktestRunsResponse>(
      request,
      timeout: timeout,
    );
  }

  Future<StartBacktestResponse> startBacktest(
    StartBacktestRequest request, {
    Duration timeout = const Duration(seconds: 2),
  }) {
    return sendRequest<StartBacktestRequest, StartBacktestResponse>(
      request,
      timeout: timeout,
    );
  }

  Future<ListInstrumentsResponse> listInstruments(
    ListInstrumentsRequest request, {
    Duration timeout = const Duration(seconds: 2),
  }) {
    return sendRequest<ListInstrumentsRequest, ListInstrumentsResponse>(
      request,
      timeout: timeout,
    );
  }

  Future<ListBarsResponse> listBars(
    ListBarsRequest request, {
    Duration timeout = const Duration(seconds: 2),
  }) {
    return sendRequest<ListBarsRequest, ListBarsResponse>(
      request,
      timeout: timeout,
    );
  }
}
