import { pond } from "protobuf-ts/pond";
import { or } from "utils/types";
import { cloneDeep } from "lodash";

export class Interaction {
  public settings: pond.InteractionSettings = pond.InteractionSettings.create();
  public status: pond.InteractionStatus = pond.InteractionStatus.create();

  public static create(pb?: pond.Interaction): Interaction {
    let my = new Interaction();
    if (pb) {
      my.settings = pond.InteractionSettings.fromObject(or(cloneDeep(pb.settings), {}));
      my.status = pond.InteractionStatus.fromObject(or(cloneDeep(pb.status), {}));
    }
    return my;
  }

  public static clone(other?: Interaction): Interaction {
    if (other) {
      return Interaction.create(
        pond.Interaction.fromObject({
          settings: cloneDeep(other.settings),
          status: cloneDeep(other.status)
        })
      );
    }
    return Interaction.create();
  }

  public static any(data: any): Interaction {
    return Interaction.create(pond.Interaction.fromObject(cloneDeep(data)));
  }

  public key(): string {
    return this.settings.key;
  }

  public conditions(): pond.InteractionCondition[] {
    return this.settings.conditions;
  }

  public subtypeFromNodes(nodeOne: number, nodeTwo: number): number {
    let subtype = 0;
    if (nodeOne > 0) {
      if (nodeTwo > 0) {
        let smallNode = nodeOne < nodeTwo ? nodeOne : nodeTwo;
        let largeNode = nodeTwo > nodeOne ? nodeTwo : nodeOne;
        subtype = this.nodeOffset(smallNode) + largeNode - smallNode - 1;
      } else {
        subtype = nodeOne + 1;
      }
    }
    return subtype;
  }

  public static upToSubtype(nodeNumber: number): number {
    let subtype = 0;
    switch (nodeNumber) {
      case 1:
        return 138;
      case 2:
        return 139;
      case 3:
        return 140;
      case 4:
        return 141;
      case 5:
        return 142;
      case 6:
        return 143;
      case 7:
        return 144;
      case 8:
        return 145;
      case 9:
        return 146;
      case 10:
        return 147;
      case 11:
        return 148;
      case 12:
        return 149;
      case 13:
        return 150;
      case 14:
        return 151;
      case 15:
        return 152;
      case 16:
        return 153;
    }
    return subtype;
  }

  private nodeOffset(node: number): number {
    let offset = 0;
    switch (node) {
      case 1:
        offset = 18;
        break;
      case 2:
        offset = 33;
        break;
      case 3:
        offset = 47;
        break;
      case 4:
        offset = 60;
        break;
      case 5:
        offset = 72;
        break;
      case 6:
        offset = 83;
        break;
      case 7:
        offset = 93;
        break;
      case 8:
        offset = 102;
        break;
      case 9:
        offset = 110;
        break;
      case 10:
        offset = 117;
        break;
      case 11:
        offset = 123;
        break;
      case 12:
        offset = 128;
        break;
      case 13:
        offset = 132;
        break;
      case 14:
        offset = 135;
        break;
      case 15:
        offset = 137;
        break;
    }
    return offset;
  }
}
