/*
 * @author lsy
 * @date   2019-09-03
 **/
import 'dart:convert';
import 'dart:core';
import 'dart:math';

import 'package:analyzer/dart/element/element.dart';
import 'package:build/src/builder/build_step.dart';
import 'package:gmalpha_flutter/Annotations/anno/ServiceCenter.dart';
import 'package:source_gen/source_gen.dart';

import '../RouterCenterRestore.dart';

class ServiceGenerator extends GeneratorForAnnotation<ServiceCenter> {
  @override
  generateForAnnotatedElement(
      Element element, ConstantReader annotation, BuildStep buildStep) {
    print("element is $element");
    if (element is! ClassElement) {
      throw InvalidGenerationSourceError(
          "Request class is not ok for ${element.displayName}");
    }
    StringBuffer improtBuffer = new StringBuffer();
    StringBuffer methodBuffer = StringBuffer("");
    StringBuffer outBuffer=StringBuffer();
    StringBuffer mapBuffer = new StringBuffer();
    List<String> differentList = [];
    for (var methodElement in (element as ClassElement).methods) {
      for (var annometadata in methodElement.metadata) {
        final metadata = annometadata.computeConstantValue();
        if (metadata.type.name == "Post" || metadata.type.name == "Get") {
          if (!differentList.contains(methodElement.returnType.name)) {
            if (methodElement.returnType.name == "SimpleResponce") {
              improtBuffer.write(
                  "import 'package:gmalpha_flutter/commonModel/net/Responce/SimpleResponce.dart';\n");
            } else {
              var pathSegments = buildStep.inputId.pathSegments;
              StringBuffer path = new StringBuffer();
              for (int i = 0; i < pathSegments.length; i++) {
                if (i < pathSegments.length - 2 && pathSegments[i] != "lib") {
                  path.write("${pathSegments[i]}/");
                }
              }
              improtBuffer.write(
                  "import 'package:${buildStep.inputId.package}/${path.toString()}entity/${methodElement.returnType.name}.dart\';\n");
            }
            differentList.add(methodElement.returnType.name);
          }
          String tempParams;
          String sendType = metadata.type.name == "Post" ? "post" : "get";

          mapBuffer.write("""
          return Observable.fromFuture(DioUtil().${sendType}(\'${metadata.getField("sufUrl").toStringValue()}\'
          """);
          bool needMap = false;
          for (int i = 0; i < methodElement.parameters.length; i++) {
            var paramsMeta = methodElement.parameters[i];
            for (int j = 0; j < paramsMeta.metadata.length; j++) {
              var parameter = paramsMeta.metadata[j];
              final queryAnno = parameter.computeConstantValue();
              if (queryAnno.type.name == "Query") {
                needMap = true;
                if (tempParams == null) {
                  tempParams = "${paramsMeta}";
                } else {
                  tempParams = "${tempParams},${paramsMeta}";
                }
                if (i == 0) {
                  mapBuffer.write(
                      ",data:{\'${queryAnno.getField("params").toStringValue()}\':${paramsMeta.name}");
                  if (methodElement.parameters.length > 1) {
                    mapBuffer.write(",");
                  } else {
                    mapBuffer.write("}");
                  }
                } else if (i == methodElement.parameters.length - 1) {
                  mapBuffer.write(
                      "\'${queryAnno.getField("params").toStringValue()}\':${paramsMeta.name}}");
                } else {
                  mapBuffer.write(
                      "\'${queryAnno.getField("params").toStringValue()}\':${paramsMeta.name},");
                }
              }
            }
          }
          //else{
          //                throw HttpException("RESPONCE error :\${value}");
          //              }

//                Map map = json.decode(value.toString());
//                return ${methodElement.returnType.name}.fromJson(map);
          mapBuffer.write("))");
          outBuffer.write("""
            ${methodElement.returnType.name} pase${methodElement.returnType.name}(String value){
              return ${methodElement.returnType.name}.fromJson(json.decode(value));
            }\n
          """);
          mapBuffer.write("""
            .flatMap((value){
              if(value!=null&&value.statusCode==200){
                  return Observable.fromFuture(compute(pase${methodElement.returnType.name}, value.toString()));
              }else {
                return Observable.fromFuture(null);
              }
            });
          """);

          methodBuffer.write("""               
                  Observable<${methodElement.returnType.name}> ${methodElement.name}(${tempParams == null ? "" : tempParams}){
                    ${mapBuffer.toString()}
                  }
                  """);
          mapBuffer.clear();
        }
      }
    }
    return """
    import 'dart:convert';\n
    import 'dart:io';\n
    import 'package:rxdart/rxdart.dart';\n
    import 'package:dio/dio.dart';\n
    import 'package:flutter/foundation.dart';\n
    ${improtBuffer.toString()}
    import 'package:gmalpha_flutter/commonModel/net/DioUtil.dart';\n
    class ${element.displayName}Impl{
        factory ${element.displayName}Impl() => _sharedInstance();

        static ${element.displayName}Impl _instance;

        ${element.displayName}Impl._() {
        }

        static ${element.displayName}Impl _sharedInstance() {
          if (_instance == null) {
            _instance = ${element.displayName}Impl._();
          }
          return _instance;
        }
      
      ${methodBuffer.toString()}
    }
    ${outBuffer.toString()}
    """;
  }
}
