'use strict';

const LOG_REGEXES = {
  zoneChange: /\[name=(.*) id=(\d+) zone=(.*) zonePos=(\d+) cardId=(.*) player=(\d)\] zone from (.*) -> (.*)/,
  zoneChangeInvalid: /\[id=(\d+) cardId= type=INVALID zone=(.*) zonePos=(\d+) player=(\d)\] zone from (.*) -> (.*)/,
  actionStart: /ACTION_START Entity=\[(.*)\] SubType=(.*) Index=-?\d+ Target=\[(.*)\]/,
  entity: /(?:name=([\w\s]+))? (?:id=(\d+))? zone=(\w+) zonePos=(\d+) cardId=(\w+) player=(\d+)/,
  start: /id=(\d) ChoiceType=MULLIGAN Cancelable=False CountMin=0 CountMax=\d/,
  finish: /Entity=(.*) tag=PLAYSTATE value=(LOST|WON|TIED)/,
  tagChange: /TAG_CHANGE Entity=(.+) tag=(\w+) value=(\w+)/
};

class LogParser {
  constructor(name) {
    this.routes = {
      'zoneChange': '_zoneChange',
      'zoneChangeInvalid': '_zoneChangeInvalid',
      'actionStart': '_actionStart',
      'start': '_start',
      'finish': '_finish',
      'tagChange': '_tagChange'
    };
  }

  parse(log) {
    for (let key in this.routes) {
      if (LOG_REGEXES[key].test(log)) {
        return this[this.routes[key]](log);
      }
    }
  }

  _zoneChange(log) {
    var parts = LOG_REGEXES.zoneChange.exec(log);
    return {
      actioType: 'zoneChange',
      name: parts[1],
      id: parts[2],
      zone: parts[3],
      zonePos: parts[4],
      cardId: parts[5],
      player: parts[6],
      from: parts[7],
      to: parts[8]
    };
  }

  _zoneChangeInvalid(log) {
    var parts = LOG_REGEXES.zoneChangeInvalid.exec(log);
    return {
      actioType: 'zoneChange',
      name: null,
      id: parts[1],
      zone: parts[2],
      zonePos: parts[3],
      cardId: null,
      player: parts[4],
      from: parts[5],
      to: parts[6]
    };
  }

  _actionStart(log) {
    var parts = LOG_REGEXES.actionStart.exec(log);
    return {
      actionType: 'actionStart',
      entity: this._parseEntity(parts[1]) || parts[1],
      target: this._parseEntity(parts[3]) || parts[3],
      subtype: parts[2]
    };
  }

  _start(log) {
    var parts = LOG_REGEXES.start.exec(log);
    return {
      actionType: 'start',
      id: parts[1]
    };
  }

  _finish(log) {
    var parts = LOG_REGEXES.finish.exec(log);
    return {
      actionType: 'finish',
      name: parts[1],
      status: parts[2]
    };
  }

  _tagChange(log) {
    var parts = LOG_REGEXES.tagChange.exec(log);
    return {
      actionType: 'tagChange',
      entity: parts[1],
      tag: parts[2],
      value: parts[3]
    };
  }

  _parseEntity(entity) {
    var parts = LOG_REGEXES.entity.exec(entity);
    if (parts !== null) {
      return {
        name: parts[1],
        id: parts[2],
        zone: parts[3],
        zonePos: parts[4],
        cardId: parts[5],
        player: parts[6]
      };
    }
    return null;
  }
}

module.exports = LogParser;

@@ -47,16 +47,26 @@
 nge: /%5C%5B
+Zone%5C%5D.*%5C%5B
 name=(.*
@@ -175,16 +175,26 @@
 lid: /%5C%5B
+Zone%5C%5D.*%5C%5B
 id=(%5Cd+)
@@ -294,16 +294,27 @@
 Start: /
+%5C%5BPower%5C%5D.*
 ACTION_S
@@ -383,301 +383,195 @@
 ,%0A  
-entity: /(?:name=(%5B%5Cw%5Cs%5D+))? (?:id=(%5Cd+))? zone=(%5Cw+) zonePos=(%5Cd+) cardId=(%5Cw+) player=(%5Cd+)/,%0A  start: /id=(%5Cd) ChoiceType=MULLIGAN Cancelable=False CountMin=0 CountMax=%5Cd/,%0A  finish: /Entity=(.*) tag=PLAYSTATE value=(LOST%7CWON%7CTIED)/,%0A  tagChange: /TAG_CHANGE Entity=(.+) tag=(%5Cw+) value=(%5Cw
+start: /%5C%5BPower%5C%5D.*CREATE_GAME/,%0A  tagChange: /TAG_CHANGE Entity=(.+) tag=(%5Cw+) value=(%5Cw+)/,%0A  entity: /(?:name=(%5B%5Cw%5Cs%5D+))? (?:id=(%5Cd+))? zone=(%5Cw+) zonePos=(%5Cd+) cardId=(%5Cw+) player=(%5Cd
 +)/%0A
@@ -751,24 +751,24 @@
 tionStart',%0A
+
       'start
@@ -784,35 +784,8 @@
 t',%0A
-      'finish': '_finish',%0A
     
@@ -1882,268 +1882,42 @@
     
-var parts = LOG_REGEXES.start.exec(log);%0A    return %7B%0A      actionType: 'start',%0A      id: parts%5B1%5D%0A    %7D;%0A  %7D%0A%0A  _finish(log) %7B%0A    var parts = LOG_REGEXES.finish.exec(log);%0A    return %7B%0A      actionType: 'finish',%0A      name: parts%5B1%5D,%0A      status: parts%5B2%5D
+return %7B%0A      actionType: 'start'
 %0A   

Clean regexes