import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:netrain_flutter_app/zhangfeng/Network/BaseHttpModel.dart';
import 'package:netrain_flutter_app/zhangfeng/UserModel.dart';
import 'BaseHttpModel.dart';
import 'UrlPath.dart';

typedef OnResult = void Function(BaseHttpModel httpModel, String errorMsg) ;

class HttpManager {
  static HttpManager _instance = HttpManager._internal();
  Dio _dio;

  factory HttpManager() => _instance;

  ///通用全局单例，第一次使用时初始化
  HttpManager._internal({String baseUrl}) {
    if (null == _dio) {
      ///connectTimeout连接超时时长
      ///receiveTimeout响应流上前后两次接受到数据的间隔，单位为毫秒。如果两次间隔超过[receiveTimeout]，[Dio] 将会抛出一个[DioErrorType.RECEIVE_TIMEOUT]的异常.注意: 这并不是接收数据的总时限
      ///sendTimeout请求超时时长
      ///如果返回数据是json(content-type)，dio默认会自动将数据转为json，
      ///
      _dio = new Dio(new BaseOptions(
          baseUrl: UrlPath.baseUrl, connectTimeout: 15000,sendTimeout: 15000));
      // 添加拦截器
      _dio.interceptors.add(InterceptorsWrapper(onRequest:
          (RequestOptions options, RequestInterceptorHandler hander) {
        print("\n================== 请求数据 ==========================");
        print("url = ${options.uri.toString()}");
        print("headers = ${options.headers}");
        print("params = ${options.data}");
        hander.next(options);
      }, onResponse: (Response response, ResponseInterceptorHandler handler) {
        print("\n================== 响应数据 ==========================");
        print("code = ${response.statusCode}");
        print("data = ${response.data}");
        print("\n");
        handler.next(response);
      }, onError: (DioError e, ErrorInterceptorHandler handler) {
        print("\n================== 错误响应数据 ======================");
        print("type = ${e.type}");
        print("message = ${e.message}");
        print("stackTrace = ${e.stackTrace}");
        print("\n");
        handler.next(e);
      }));
    }
  }

  static HttpManager getInstance({String baseUrl}) {
    if (baseUrl == null) {
      return _instance._normal();
    } else {
      return _instance._baseUrl(baseUrl);
    }
  }

  //用于指定特定域名
  HttpManager _baseUrl(String baseUrl) {
    if (_dio != null) {
      _dio.options.baseUrl = baseUrl;
    }
    return this;
  }

  //一般请求，默认域名
  HttpManager _normal() {
    if (_dio != null) {
      if (_dio.options.baseUrl != UrlPath.baseUrl) {
        _dio.options.baseUrl = UrlPath.baseUrl;
      }
    }
    return this;
  }

  request(String url,
      {parameters,
        method = 'GET',
        OnResult onResult,List images}) async {
    parameters = parameters ?? {};
    if(onResult==null){
      return;
    }
    try {
      FormData formdata;
      if(images != null){
        List<MultipartFile> imageList = new List<MultipartFile>();
        for (String imagePath in images) {
          var name = imagePath.substring(imagePath.lastIndexOf("/") + 1, imagePath.length);
          var suffix = name.substring(name.lastIndexOf(".") + 1, name.length);
          MultipartFile multipartFile = await MultipartFile.fromFile(
            imagePath,
            //这个字段要有，否则后端接收为null
            filename: name,
          );
          imageList.add(multipartFile);
        }

        formdata = new FormData.fromMap({
          //后端要用multipartFiles接收参数，否则为null
          "multipartFiles" : imageList
        });
      }
      parameters = new Map<String, dynamic>.from(parameters);
      Map<String,String> headers = new Map<String,String>();
      if(UserModel.getModel() != null) {
        headers[UserModel.getModel().header] = UserModel.getModel().tokenHead + UserModel.getModel().token;
      }
      Response response = await _dio.request(url,
          queryParameters: parameters, data: formdata, options: new Options(method: method,headers: headers,responseType: ResponseType.plain));
      Map<String, dynamic> result = json.decode(response.toString());
      BaseHttpModel httpModel = BaseHttpModel.fromJson(result);
      if (httpModel.isSuccess()) {
        onResult(httpModel, null);
      }else{
        onResult(httpModel, httpModel.errorMsg());
      }
    } on DioError catch (e) {
      onResult(null, e.message);
    }
  }
}
