import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';

import '../schemas/device_info_model.dart';
import '../schemas/device_model.dart';

Future<Map<String, dynamic>> readJson() async {
  final String data = await rootBundle.loadString('config/credentials.json');
  final Map<String, dynamic> dataMap = json.decode(data);
  log("loaded json input $dataMap");
  return dataMap;
}

class CloudServiceAPI {
  static late final Map<String, dynamic> credentials;
  static String _basicAuth = "";
  static String _address = "";
  static String _username = "";
  static String _password = "";
  static late Map<String, String> _headers;
  static bool _initState = false;
  static List<DeviceModel> devices = List<DeviceModel>.empty(growable: true);

  CloudServiceAPI() {
    if (!_initState) {
      loadConfig();
      _initState = true;
    }
  }

  Future<void> loadConfig() async {
    credentials = await readJson();
    _username = credentials['username'];
    _password = credentials['password'];
    _address = credentials['address'];
    _basicAuth = 'Basic ${base64.encode(utf8.encode('$_username:$_password'))}';
    _headers = {
      'authorization': _basicAuth,
      'content-type': 'application/json',
      'accept': 'application/json',
    };
    log("init Config $_headers");
    await updateDeviceList();
  }

  Future<void> reloadConfig() async {
    _basicAuth = 'Basic ${base64.encode(utf8.encode('$_username:$_password'))}';
    _headers = {
      'authorization': _basicAuth,
      'content-type': 'application/json',
      'accept': 'application/json',
    };
  }

  Future<List<DeviceModel>> getDevices() async {
    Uri url = Uri.https(_address, '/api/devices');
    Response responnse = await get(url, headers: _headers);
    dynamic jsonObject = json.decode(responnse.body);
    Iterable<dynamic> remoteObjectsIterable = Iterable.castFrom(jsonObject);
    Iterable<DeviceModel> remoteObjectsMap = remoteObjectsIterable.map((data) => DeviceModel.fromJson(data));
    List<DeviceModel> remoteObjectsList = remoteObjectsMap.toList();
    return remoteObjectsList;
  }
  Future<DeviceInfoModel> getDeviceInfo(String deviceID) async {
    Uri url = Uri.https(_address, '/api/devices/$deviceID');
    Response response = await get(url, headers: _headers);
    dynamic jsonObject = json.decode(response.body);
    DeviceInfoModel deviceInfoModel = DeviceInfoModel.fromJson(jsonObject);
    return deviceInfoModel;
  }
  Future<List<DeviceInfoModel>> getDevicesInfo() async {
    updateDeviceList();
    List<DeviceInfoModel> deviceInfoModelList = List<DeviceInfoModel>.empty(growable: true);
    for(DeviceModel tmp in devices){
      deviceInfoModelList.add(await getDeviceInfo(tmp.id));
    }
    return deviceInfoModelList;
  }
  Future updateDeviceList() async {
    devices = await getDevices();
  }

  Future<Map<String, dynamic>> getInformation() async {
    Uri url = Uri.https(_address, '/api/app');
    Response response = await get(url, headers: _headers);
    return json.decode(response.body) as Map<String, dynamic>;
  }
  Future<bool> deleteDevice(String clientId) async {
    Uri url = Uri.https(_address, '/api/devices/$clientId');
    Response response = await delete(url, headers: _headers);
    if(response.statusCode == 204){
      return true;
    }
    return false;
  }

  Future<bool> createDevice(String id, String primaryThumbprint, String secondaryThumbprint) async {
    Uri url = Uri.https(_address, '/api/devices');
    Response response = await post(url,
        headers: _headers,
        body: jsonEncode(<String, String>{
          'id': id,
          'primaryThumbprint': primaryThumbprint,
          'secondaryThumbprint': secondaryThumbprint
        }));
    if (response.statusCode == 200) {
      return true;
    }
    debugPrint('Error createDevice: ${response.statusCode.toString()}');
    return false;
  }

  Future<bool> checkNameAvailability(String inputID) async {
    // await cloudServiceAPI.loadConfig();
    List<DeviceModel> devices = await getDevices();
    for (DeviceModel selected in devices) {
      if (selected.id == inputID) {
        debugPrint("ID 1: ${selected.id}");
        debugPrint("ID 2: $inputID");
        await showNameAvailabilityStatus(false);
        return false;
      }
    }
    await showNameAvailabilityStatus(true);
    return true;
  }

  Future<void> showNameAvailabilityStatus(bool status) async {
    String statusText = status ? "die eingegebene ID ist verfügbar" : "die eingegebene ID ist nicht verfügbar";
    Fluttertoast.showToast(
        msg: statusText,
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.BOTTOM,
        timeInSecForIosWeb: 2,
        backgroundColor: Colors.grey[200],
        textColor: Colors.black,
        fontSize: 16.0);
  }

  String get address {
    return _address;
  }

  String get username {
    return _username;
  }

  String get password {
    return _password;
  }

  set address(String input) {
    _address = input;
    reloadConfig();
  }

  set username(String input) {
    _username = input;
    reloadConfig();
  }

  set password(String input) {
    _password = input;
    reloadConfig();
  }
  List<dynamic> getLoadedDevices(){
    return devices;
  }
}
