import _ from 'lodash';

export class SegmentationType {
  static secondary_structure = new SegmentationType("secondary_structure");
  static custom = new SegmentationType("custom");
  static invalid = new SegmentationType("invalid");
  static loop = new SegmentationType("loop");


  constructor(name) {
    this.name = name;
  }
}

export class Segment {
  constructor(from_acid, to_acid, name, type, assignment = null, ss = null, ss_segment_list = null) {
    this.from_acid = from_acid;
    this.to_acid = to_acid;
    this.from = from_acid.pdb_number;
    this.to = to_acid.pdb_number;
    this.name = name;
    this.type = type;
    this.assignment = assignment;
    this.ss = ss;
    this.ss_segment_list = ss_segment_list;
  }

  get customized() {
    return this.type == SegmentationType.custom;
  }

  get valid() {
    return this.type == SegmentationType.invalid;
  }

  cut(from, to) {
    if (from <= this.from && this.from <= to) {
      this.from = to + 1;
    }

    if (from <= this.to && this.to <= to) {
      this.to = from - 1;
    }
  }

  containsWholeSegment(segment) {
    return this.from <= segment.from && segment.to <= this.to;
  }

  isContained(segment) {
    return this.from >= segment.from && segment.to >= this.to;
  }

  containsAcid(acid) {
    return this.from <= acid.pdb_number && acid.pdb_number <= this.to;
  }

}



export class Segmentation {
  constructor(protein) {
    this.segments = [];
    this.segmentCount = 0;

    this.customized = false;
    this.acids = protein.acids;
    this.protein = protein;
    this.invalidUntil = null;
    this.invalidTo = null;
    this.setDefaultSegmentation();
  }

  setDefaultSegmentation() {
    this.segments = [];
    this.customized = false;
    let from = 0;

    // secs 
    for (let i = 0; i < this.acids.length; i++) {
      if (this.acids[from].simple_secondary_structure != this.acids[i].simple_secondary_structure) {
        let to = i - 1;
        let name = this.acids[from].simple_secondary_structure + this.segments.length.toString();
        this.segments.push(new Segment(this.acids[from], this.acids[to], name, SegmentationType.secondary_structure, this.acids[from].simple_secondary_structure));
        from = i;
      }
    }
    let to = this.acids.length - 1;
    let name = this.acids[from].simple_secondary_structure + this.segments.length.toString();
    this.segments.push(new Segment(this.acids[from], this.acids[to], name, SegmentationType.secondary_structure, this.acids[from].simple_secondary_structure));


    //loops
    for (let loop of this.protein.loops) {
      let start = this.protein.getAcid(loop.start);
      let end = this.protein.getAcid(loop.end);
      let acids = this.protein.getAcids(start.pdb_number, end.pdb_number);
      let ss = []
      let ss_segments = []
      ss.push(start.simple_secondary_structure);
      let has_coil = false;
      for(let acid of acids){
        if(acid.simple_secondary_structure == 'C'){
          has_coil = true
        }

        let secs = this.getSegmentByAcid(acid, SegmentationType.secondary_structure);
        if(!ss_segments.includes(secs)){
          ss_segments.push(secs)
        }
      }
      ss.push(has_coil ? 'C' : 'X');
      ss.push(end.simple_secondary_structure);
      let newSegment = new Segment(start, end, loop.id, SegmentationType.loop, null,  ss.join(''), ss_segments.map(s => s.name));
      this.segments.push(newSegment);
    }

    this.segments = _.sortBy(this.segments, s => s.from);
  }

  removeSegment(segment) {
    this.segments = this.segments.filter((s) => s.name != segment.name);
  }

  empty() {
    this.segments = [];
    this.customized = false;
  }

  getSegmentByAcid(acid, type = null) {
    let segment = this.segments.filter(s => s.containsAcid(acid)).filter(s => type ? s.type == type : true);
    if (segment.length == 0) {
      return null;
    } else {
      return segment[0];
    }
  }

  getSegmentByName(name){
    let segment = this.segments.filter(s => s.name == name)
    if (segment.length == 0) {
      return null;
    } else {
      return segment[0];
    }
  }
}