|  |  |  | import 'dart:async'; | 
					
						
							|  |  |  | import 'dart:convert'; | 
					
						
							|  |  |  | import 'dart:io'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import 'package:flutter/foundation.dart'; | 
					
						
							|  |  |  | import 'package:http/http.dart'; | 
					
						
							|  |  |  | import 'package:http/io_client.dart'; | 
					
						
							|  |  |  | import 'package:mohem_flutter_app/app_state/app_state.dart'; | 
					
						
							|  |  |  | import 'package:mohem_flutter_app/exceptions/api_exception.dart'; | 
					
						
							|  |  |  | import 'package:mohem_flutter_app/main.dart'; | 
					
						
							|  |  |  | // ignore_for_file: avoid_annotating_with_dynamic
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef FactoryConstructor<U> = U Function(dynamic); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class APIError { | 
					
						
							|  |  |  |   int? errorCode; | 
					
						
							|  |  |  |   int? errorType; | 
					
						
							|  |  |  |   String? errorMessage; | 
					
						
							|  |  |  |   int?    errorStatusCode; | 
					
						
							|  |  |  |   APIError(this.errorCode, this.errorMessage, this.errorType, this.errorStatusCode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Map<String, dynamic> toJson() => { | 
					
						
							|  |  |  |         'errorCode': errorCode, | 
					
						
							|  |  |  |         'errorMessage': errorMessage, | 
					
						
							|  |  |  |         'errorType': errorType, | 
					
						
							|  |  |  |         'ErrorStatusCode':  errorStatusCode | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   String toString() { | 
					
						
							|  |  |  |     return jsonEncode(this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | APIException _throwAPIException(Response response) { | 
					
						
							|  |  |  |   switch (response.statusCode) { | 
					
						
							|  |  |  |     case 200: | 
					
						
							|  |  |  |       APIError? apiError; | 
					
						
							|  |  |  |       if (response.body != null && response.body.isNotEmpty) { | 
					
						
							|  |  |  |         var jsonError = jsonDecode(response.body); | 
					
						
							|  |  |  |         print(jsonError); | 
					
						
							|  |  |  |         apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'], jsonError['ErrorStatusCode']); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return APIException(APIException.BAD_REQUEST, error: apiError); | 
					
						
							|  |  |  |     case 400: | 
					
						
							|  |  |  |       APIError? apiError; | 
					
						
							|  |  |  |       if (response.body != null && response.body.isNotEmpty) { | 
					
						
							|  |  |  |         var jsonError = jsonDecode(response.body); | 
					
						
							|  |  |  |         apiError = APIError(jsonError['ErrorCode'], jsonError['ErrorMessage'], jsonError['ErrorType'],jsonError['ErrorStatusCode']); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return APIException(APIException.BAD_REQUEST, error: apiError); | 
					
						
							|  |  |  |     case 401: | 
					
						
							|  |  |  |       return APIException(APIException.UNAUTHORIZED); | 
					
						
							|  |  |  |     case 403: | 
					
						
							|  |  |  |       return APIException(APIException.FORBIDDEN); | 
					
						
							|  |  |  |     case 404: | 
					
						
							|  |  |  |       return APIException(APIException.NOT_FOUND); | 
					
						
							|  |  |  |     case 500: | 
					
						
							|  |  |  |       return APIException(APIException.INTERNAL_SERVER_ERROR); | 
					
						
							|  |  |  |     case 444: | 
					
						
							|  |  |  |       var downloadUrl = response.headers["location"]; | 
					
						
							|  |  |  |       return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl); | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return APIException(APIException.OTHER); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ApiClient { | 
					
						
							|  |  |  |   static final ApiClient _instance = ApiClient._internal(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ApiClient._internal(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   factory ApiClient() => _instance; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject, | 
					
						
							|  |  |  |       {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async { | 
					
						
							|  |  |  |     var _headers = {'Accept': 'application/json'}; | 
					
						
							|  |  |  |     if (headers != null && headers.isNotEmpty) { | 
					
						
							|  |  |  |       _headers.addAll(headers); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!kReleaseMode) { | 
					
						
							|  |  |  |       print("Url:$url"); | 
					
						
							|  |  |  |       var bodyJson = json.encode(jsonObject); | 
					
						
							|  |  |  |       print("body:$bodyJson"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes, isFormData: isFormData); | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       if (!kReleaseMode) { | 
					
						
							|  |  |  |         logger.i("Url: " + url); | 
					
						
							|  |  |  |         logger.i("res: " + response.body); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var jsonData = jsonDecode(response.body); | 
					
						
							|  |  |  |       if (jsonData["IsAuthenticated"] != null) { | 
					
						
							|  |  |  |         AppState().setIsAuthenticated = jsonData["IsAuthenticated"]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // if(url.contains("GetOfferDiscountsConfigData")) {
 | 
					
						
							|  |  |  |       //   jsonData["ErrorMessage"] = "Service Not Available";
 | 
					
						
							|  |  |  |       //   jsonData["ErrorEndUserMessage"] = "Service Not Available";
 | 
					
						
							|  |  |  |       // }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (jsonData["ErrorMessage"] == null) { | 
					
						
							|  |  |  |         return factoryConstructor(jsonData); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         APIError? apiError; | 
					
						
							|  |  |  |         apiError = APIError(jsonData['ErrorCode'], jsonData['ErrorEndUserMessage'], jsonData['ErrorType'] ?? 0, jsonData['ErrorStatusCode']); | 
					
						
							|  |  |  |         throw APIException(APIException.BAD_REQUEST, error: apiError); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } catch (ex) { | 
					
						
							|  |  |  |       if (ex is APIException) { | 
					
						
							|  |  |  |         rethrow; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<Response> postJsonForResponse<T>(String url, T jsonObject, | 
					
						
							|  |  |  |       {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async { | 
					
						
							|  |  |  |     String? requestBody; | 
					
						
							|  |  |  |     late Map<String, String> stringObj; | 
					
						
							|  |  |  |     if (jsonObject != null) { | 
					
						
							|  |  |  |       requestBody = jsonEncode(jsonObject); | 
					
						
							|  |  |  |       if (headers == null) { | 
					
						
							|  |  |  |         headers = {'Content-Type': 'application/json'}; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         headers['Content-Type'] = 'application/json'; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isFormData) { | 
					
						
							|  |  |  |       headers = {'Content-Type': 'application/x-www-form-urlencoded'}; | 
					
						
							|  |  |  |       stringObj = ((jsonObject ?? {}) as Map<String, dynamic>).map((key, value) => MapEntry(key, value?.toString() ?? "")); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return await _postForResponse(url, isFormData ? stringObj : requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<Response> _postForResponse(String url, requestBody, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       var _headers = <String, String>{}; | 
					
						
							|  |  |  |       if (token != null) { | 
					
						
							|  |  |  |         _headers['Authorization'] = 'Bearer $token'; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (headers != null && headers.isNotEmpty) { | 
					
						
							|  |  |  |         _headers.addAll(headers); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (queryParameters != null) { | 
					
						
							|  |  |  |         var queryString = new Uri(queryParameters: queryParameters).query; | 
					
						
							|  |  |  |         url = url + '?' + queryString; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 120)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (response. statusCode >= 200 && response.statusCode < 300) { | 
					
						
							|  |  |  |         return response; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw _throwAPIException(response); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } on SocketException catch (e) { | 
					
						
							|  |  |  |       if (retryTimes > 0) { | 
					
						
							|  |  |  |         print('will retry after 3 seconds...'); | 
					
						
							|  |  |  |         await Future.delayed(Duration(seconds: 3)); | 
					
						
							|  |  |  |         return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw APIException(APIException.OTHER, arguments: e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } on HttpException catch (e) { | 
					
						
							|  |  |  |       if (retryTimes > 0) { | 
					
						
							|  |  |  |         print('will retry after 3 seconds...'); | 
					
						
							|  |  |  |         await Future.delayed(Duration(seconds: 3)); | 
					
						
							|  |  |  |         return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw APIException(APIException.OTHER, arguments: e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } on TimeoutException catch (e) { | 
					
						
							|  |  |  |       throw APIException(APIException.TIMEOUT, arguments: e); | 
					
						
							|  |  |  |     } on ClientException catch (e) { | 
					
						
							|  |  |  |       if (retryTimes > 0) { | 
					
						
							|  |  |  |         print('will retry after 3 seconds...'); | 
					
						
							|  |  |  |         await Future.delayed(Duration(seconds: 3)); | 
					
						
							|  |  |  |         return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw APIException(APIException.OTHER, arguments: e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<Response> getJsonForResponse<T>(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async { | 
					
						
							|  |  |  |     if (headers == null) { | 
					
						
							|  |  |  |       headers = {'Content-Type': 'application/json'}; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       headers['Content-Type'] = 'application/json'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!kReleaseMode) { | 
					
						
							|  |  |  |       print("Url:$url"); | 
					
						
							|  |  |  |       // var bodyJson = json.encode(jsonObject);
 | 
					
						
							|  |  |  |       // print("body:$bodyJson");
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<Response> _getForResponse(String url, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       var _headers = <String, String>{}; | 
					
						
							|  |  |  |       if (token != null) { | 
					
						
							|  |  |  |         _headers['Authorization'] = 'Bearer $token'; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (headers != null && headers.isNotEmpty) { | 
					
						
							|  |  |  |         _headers.addAll(headers); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (queryParameters != null) { | 
					
						
							|  |  |  |         var queryString = new Uri(queryParameters: queryParameters).query; | 
					
						
							|  |  |  |         url = url + '?' + queryString; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       var response = await _get(Uri.parse(url), headers: _headers).timeout(Duration(seconds: 60)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (response.statusCode >= 200 && response.statusCode < 300) { | 
					
						
							|  |  |  |         return response; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw _throwAPIException(response); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } on SocketException catch (e) { | 
					
						
							|  |  |  |       if (retryTimes > 0) { | 
					
						
							|  |  |  |         print('will retry after 3 seconds...'); | 
					
						
							|  |  |  |         await Future.delayed(Duration(seconds: 3)); | 
					
						
							|  |  |  |         return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw APIException(APIException.OTHER, arguments: e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } on HttpException catch (e) { | 
					
						
							|  |  |  |       if (retryTimes > 0) { | 
					
						
							|  |  |  |         print('will retry after 3 seconds...'); | 
					
						
							|  |  |  |         await Future.delayed(Duration(seconds: 3)); | 
					
						
							|  |  |  |         return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw APIException(APIException.OTHER, arguments: e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } on TimeoutException catch (e) { | 
					
						
							|  |  |  |       throw APIException(APIException.TIMEOUT, arguments: e); | 
					
						
							|  |  |  |     } on ClientException catch (e) { | 
					
						
							|  |  |  |       if (retryTimes > 0) { | 
					
						
							|  |  |  |         print('will retry after 3 seconds...'); | 
					
						
							|  |  |  |         await Future.delayed(Duration(seconds: 3)); | 
					
						
							|  |  |  |         return await _getForResponse(url, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         throw APIException(APIException.OTHER, arguments: e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<Response> _get(url, {Map<String, String>? headers}) => _withClient((client) => client.get(url, headers: headers)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool _certificateCheck(X509Certificate cert, String host, int port) => true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<T> _withClient<T>(Future<T> Function(Client) fn) async { | 
					
						
							|  |  |  |     var httpClient = HttpClient()..badCertificateCallback = _certificateCheck; | 
					
						
							|  |  |  |     var client = IOClient(httpClient); | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       return await fn(client); | 
					
						
							|  |  |  |     } finally { | 
					
						
							|  |  |  |       client.close(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<Response> _post(url, {Map<String, String>? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding)); | 
					
						
							|  |  |  | } |