import 'package:oto/oto/commands/command.dart';
import 'package:oto/oto/data/command_data.dart';

class SetValueCommand extends Command {
  Function? get error => null;

  @override
  Future execute(DataCommand command) async {
    var data = DataSetValue.fromJson(getParam(command));

    if (data.values_bool != null) {
      for (var pair in data.values_bool!.entries) {
        bool value = false;
        if (pair.value is bool) {
          value = pair.value;
        } else if (pair.value is String) {
          var resultTag = replaceSingleTag(pair.value);
          if (resultTag is String) {
            var toLow = resultTag.toLowerCase();
            if (toLow == 'true' || toLow == 'false') {
              value = toLow == 'true';
            }
          } else if (resultTag is bool) {
            value = resultTag;
          }
        }
        await setProperty(getTag(pair.key), value);
      }
    }

    if (data.values_float != null) {
      for (var pair in data.values_float!.entries) {
        double value = 0;
        if (pair.value is double) {
          value = pair.value;
        } else if (pair.value is String) {
          var resultTag = replaceSingleTag(pair.value);
          if (resultTag is String) {
            value = double.parse(resultTag);
          } else if (resultTag is double) {
            value = resultTag;
          } else if (resultTag is int) {
            value = resultTag + 0.0;
          }
        }
        await setProperty(getTag(pair.key), value);
      }
    }

    if (data.values_int != null) {
      for (var pair in data.values_int!.entries) {
        var value = 0;
        if (pair.value is int) {
          value = pair.value;
        } else if (pair.value is String) {
          var resultTag = replaceSingleTag(pair.value);
          if (resultTag is String) {
            value = int.parse(resultTag);
          } else if (resultTag is int) {
            value = resultTag;
          } else if (resultTag is double) {
            value = resultTag.round();
          }
        }
        await setProperty(getTag(pair.key), value);
      }
    }

    if (data.values_string != null) {
      for (var pair in data.values_string!.entries) {
        await setProperty(getTag(pair.key), pair.value);
      }
    }

    if (data.values_object != null) {
      for (var pair in data.values_object!.entries) {
        await setProperty(getTag(pair.key), pair.value);
      }
    }

    return complete(0, command);
  }

  String getTag(String key) {
    return '<@property.$key>';
  }
}

void registerSetValueCommand() {
  Command.register(
    CommandType.SetValue,
    () => SetValueCommand(),
    spec: const CommandSpec(
      type: CommandType.SetValue,
      category: 'util',
      dataModel: 'DataSetValue',
      samplePath: 'assets/yaml/sample/01_basic.yaml',
    ),
  );
}
