import 'package:oc_front/models/abstract.dart';
import 'package:oc_front/models/logs.dart';
import 'package:oc_front/models/resources/compute.dart';
import 'package:oc_front/models/resources/data.dart';
import 'package:oc_front/models/resources/processing.dart';
import 'package:oc_front/models/resources/resources.dart';
import 'package:oc_front/models/resources/storage.dart';
import 'package:oc_front/models/search.dart';
import 'package:oc_front/models/shared.dart';
import 'package:oc_front/models/workflow.dart';
import 'package:oc_front/models/workspace.dart';

Map<Type, SerializerDeserializer> refs = <Type, SerializerDeserializer> {
  RawData: RawData(),
  Search: Search(),
  Workspace: Workspace(),
  DataItem: DataItem(),
  ComputeItem: ComputeItem(),
  StorageItem: StorageItem(),
  ProcessingItem: ProcessingItem(),
  Workflow: Workflow(),
  Resource: Resource(),
  WorkflowExecutions: WorkflowExecutions(),
  LogsResult: LogsResult(),
  Check: Check(),
  CollaborativeArea: CollaborativeArea(),
  SimpleData: SimpleData(),
  EnumData: EnumData(),
};

class APIResponse<T extends SerializerDeserializer> {
  APIResponse({
    this.data,
    this.code = 200,
    this.error = "",
    this.offset = 0,
  });
  int code = 200;
  int offset = 0;
  T? data ;
  String? error = "";

  SerializerDeserializer? getTypeString() {
    try {  return refs[refs.keys.firstWhere((ref) => '$ref' == '$T')];
    } catch (e) { return null; }
  }

  APIResponse<T> deserialize(dynamic j) {
    dynamic data;
    try { 
      if (j["data"] == null) { data = j; }
      else {
        data = j["data"];
      }
    } catch (e) { data = j; }
    try {
      return APIResponse<T>(
        data: refs[T]!.deserialize(data), 
        code: j.containsKey("code") && j["code"] != null ? j["code"] : 200,
        error: j.containsKey("error") && j["error"] != null ? j["error"] : "",
      );
    } catch (e) { 
      return APIResponse<T>( data: refs[T]?.deserialize(data), ); 
    }
  }
}

class SimpleData extends SerializerDeserializer<SimpleData> {
  SimpleData({ this.value });
  dynamic value;
  @override deserialize(dynamic json) { 
    return SimpleData(value: json); 
  }
  @override Map<String, dynamic> serialize() => { };
}

class EnumData extends SerializerDeserializer<EnumData> {
  EnumData({ this.value = const {} });
  Map<String, dynamic> value = {};
  @override deserialize(dynamic json) { 
    return EnumData(value: json as Map<String, dynamic>); 
  }
  @override Map<String, dynamic> serialize() => { };
}

class RawData extends SerializerDeserializer<RawData> {
  RawData({ this.values = const []});
  List<dynamic> values = [];
  @override deserialize(dynamic json) { 
    try {
      return RawData(values: json ?? []); 
    } catch (e) { 
      print(e);
      print(json);
      return RawData(); 
    }
  }
  @override Map<String, dynamic> serialize() => { };
}

abstract class ShallowData {
  String getID();
  String getName();
  Map<String, dynamic> serialize();
}

class Shallow {
  String id;
  String name;
  Shallow({
    this.id = "",
    this.name = "",
  });
}