#include "MemoryManager.h"
#include "spnbox.h"
#include "matrixmath.h"
#include "../pnheaders/matrix.h"
#include "../pnheaders/pns.h"

int disj2pn(pns *bin, matrix* ld, int* cd, matrix* D, matrix* m0m, int* plant_label, matrix* l, int c, int lb, int ub, int bin_current, int bin_total)
{
  matrix lneg, bin_Dm, bin_Dp, l_m0, lD;
  int i, j;
  int* bin_label;
  int bin_label_length;
  int* lD_nonzero_index;
  int lD_vector[D->nc];
  int tmp_lD;
  int l_m0_int;
  int bin_m0, bin_tnum;
  int *bin_2label;
  MemoryManager memory;

  memory = CreateMemoryManager(20, 20, 0, 0);
  ManageMatrix(&memory, m0m);

  MAllocateMatrixType(&memory, 2, &lneg, l->nr, l->nc);
  for(i = 0; i < l->nr; i++)
    for(j = 0; j < l->nc; j++)
      SetMatrixEl(&lneg, i, j, GetMatrixEl(l, i, j) * (-1));

  for(i = 0; i < ld->nr; i++)
    MakeZeroRow(ld, i);
  CopyBlock(l->nr, l->nc, l, 0, 0, ld, 0, 0);
  CopyBlock(l->nr, l->nc, &lneg, 0, 0, ld, l->nr, 0);
  SetMatrixEl(ld, 0, l->nc + (bin_current > 0 ? bin_current : 0), ub - c);
  SetMatrixEl(ld, 1, l->nc + (bin_current > 0 ? bin_current : 0), -(c+1 - lb));
  cd[0] = ub;
  cd[1] = -(c+1);
  
  MAllocateMatrixType(&memory, 2, &l_m0, 1, 1);
  MultiplyMatrix(l, m0m, &l_m0);
  l_m0_int = GetMatrixEl(&l_m0, 0, 0);
  bin_m0 = (l_m0_int <= c) ? 1 : 0;

  MAllocateMatrixType(&memory, 2, &lD, 1, D->nc);
  MultiplyMatrix(l, D, &lD);

  for(i = 0; i< lD.nc; i++)
    lD_vector[i] = GetMatrixEl(&lD, 0, i);
  bin_label_length = findIndices(lD_vector, lD.nc, sizeof(int), &lD_nonzero_index);
  
  bin_label = mmalloc(&memory, bin_label_length * sizeof(int));
  bin_2label = mmalloc(&memory, 2 * bin_label_length * sizeof(int));
  for(i = 0; i < bin_label_length; i++) {
    bin_label[i] = plant_label[lD_nonzero_index[i]];
    bin_2label[i] = bin_label[i];
    bin_2label[bin_label_length + i] = bin_label[i];
  }

  bin_tnum = 2 * bin_label_length;

  AllocateMatrix(&bin_Dm, 1, bin_tnum);
  AllocateMatrix(&bin_Dp, 1, bin_tnum);

  for(i = 0; i < bin_label_length; i++) {
    tmp_lD = lD_vector[lD_nonzero_index[i]];
    if(tmp_lD > 0)
      SetMatrixEl(&bin_Dm, 0, i, 1);
    else
      SetMatrixEl(&bin_Dp, 0, i, 1);
  }

  *bin = createpn("mDm mDp m0 label", bin_Dm, bin_Dp, &bin_m0, bin_2label);
  FreeMemory(&memory);
}
