#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"util.h"
#include"movements.h"

int movement_eos(config *c, int movement_code)
{
  if(stack_is_empty(config_get_stack(c))) return 0;
  word *s0 = stack_top(config_get_stack(c));

  /* word on top of stack is already eos */
  if(word_get_sent_seg(s0) == 1) return 0;
  
  /* set word on the top of the stack to eos */
  word_set_sent_seg(s0, 1); 

  config_push_mvt(c, movement_code, s0, NULL);
    
  return 1;
}

int movement_eos_undo(config *c)
{
  word *gov = mvt_get_gov(mvt_stack_top(config_get_history(c)));
  
  /* word on the top of the stack is not eos anymore */
  word_set_sent_seg(gov, 0); 

  mvt_free(config_pop_mvt(c));
  return 1;
}

int movement_left_arc(config *c, int movement_code, int label)
{
  if(stack_is_empty(config_get_stack(c))) return 0;  
  /* if(word_buffer_is_empty(config_get_buffer(c))) return 0; */
  
  /* word on top of the stack should not have a governor */ // com here bug ?
  if(word_get_gov(stack_top(config_get_stack(c))) != WORD_INVALID_GOV) return 0;
  
  word *gov = word_buffer_b0(config_get_buffer(c));
  word *dep = stack_top(config_get_stack(c));
  int dist = (word_get_index(gov)) - (word_get_index(dep));

  /* create a new dependency */
  word_set_gov(dep, dist);
  word_set_label(dep, label);

  config_push_mvt(c, movement_code, gov, dep);

  stack_pop(config_get_stack(c));
  return 1;
}

int movement_left_arc_undo(config *c)
{
  
  word *dep = mvt_get_dep(mvt_stack_top(config_get_history(c)));

  /* undo dependency */
  word_set_gov(dep, WORD_INVALID_GOV);
  word_set_label(dep, -1);

  mvt_free(config_pop_mvt(c));

  stack_push(config_get_stack(c), dep);
  return 1;
}


int movement_right_arc(config *c, int movement_code, int label)
{
  if(stack_is_empty(config_get_stack(c))) return 0;
  if(word_buffer_end(config_get_buffer(c))) return 0;
  
  word *gov = stack_top(config_get_stack(c));
  word *dep = word_buffer_b0(config_get_buffer(c));
  int dist = (word_get_index(gov)) - (word_get_index(dep));

  /* create a new dependency */
  word_set_gov(dep, dist);
  word_set_label(dep, label);
  
  stack_push(config_get_stack(c), word_buffer_b0(config_get_buffer(c)));
  word_buffer_move_right(config_get_buffer(c));

  config_push_mvt(c, movement_code, gov, dep);
  return 1;
}

int movement_right_arc_undo(config *c)
{
  word *dep = mvt_get_dep(mvt_stack_top(config_get_history(c)));

  /* undo dependency */
  word_set_gov(dep, WORD_INVALID_GOV);
  word_set_label(dep, -1);
  
  stack_pop(config_get_stack(c));
  word_buffer_move_left(config_get_buffer(c));
  mvt_free(config_pop_mvt(c));
  return 1;
}

int movement_shift(config *c, int movement_code)
{
  /* if(word_buffer_is_empty(config_get_buffer(c))) return 0; */
  if(word_buffer_end(config_get_buffer(c))) return 0;


  word *b0 = word_buffer_b0(config_get_buffer(c));
  stack_push(config_get_stack(c), b0);
  config_push_mvt(c, movement_code, b0, NULL);
  word_buffer_move_right(config_get_buffer(c));
  return 1;
}

int movement_shift_undo(config *c)
{
  stack_pop(config_get_stack(c));
  mvt_free(config_pop_mvt(c));
  word_buffer_move_left(config_get_buffer(c));
  return 1;
}

int movement_reduce(config *c, int movement_code)
{
  if(stack_nbelem(config_get_stack(c)) <= 1) return 0;
  word *s0 = stack_top(config_get_stack(c));
  /* word on top of stack must have a governor */
  if(word_get_gov(s0) == WORD_INVALID_GOV) return 0; 

  config_push_mvt(c, movement_code, s0, NULL);
  stack_pop(config_get_stack(c));
  return 1;
}

int movement_reduce_undo(config *c)
{
  word *gov = mvt_get_gov(mvt_stack_top(config_get_history(c)));
  mvt_free(config_pop_mvt(c));
  stack_push(config_get_stack(c), gov);
  return 1;
}

int movement_root(config *c, int movement_code, int root_code)
{
  if(stack_is_empty(config_get_stack(c))) return 0;
  word *s0 = stack_top(config_get_stack(c));
  word_set_gov(s0, 0);
  word_set_label(s0, root_code);
  s0->is_root = 1;

  stack_pop(config_get_stack(c));

  config_push_mvt(c, movement_code, s0, NULL);
  return 1;
}

int movement_root_undo(config *c)
{
  word *gov = mvt_get_gov(mvt_stack_top(config_get_history(c)));
  if(gov == NULL) return 0;
  word_set_gov(gov, WORD_INVALID_GOV);
  word_set_label(gov, -1);
  gov->is_root = 0;

  stack_push(config_get_stack(c), gov);
  mvt_free(config_pop_mvt(c));
  return 1;
}

int movement_add_pos(config *c, int movement_code, int pos)
{
  if(word_buffer_b0(config_get_buffer(c)) == NULL) return 0;
  word *b0 = word_buffer_b0(config_get_buffer(c));
  if(word_get_pos(b0) != -1) return 0;
  word_set_pos(b0, pos);
  config_push_mvt(c, movement_code, b0, NULL); 
  return 1;
}

int movement_add_pos_undo(config *c)
{
  word *gov = mvt_get_gov(mvt_stack_top(config_get_history(c)));
  word_set_pos(gov, -1);
  mvt_free(config_pop_mvt(c));
  return 1;
}