/**
* Arquivo responsavel pela leitura e escrita dos arquivos XYZ
*/
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>

#define sqr1(x) (x*x)

const int tamanho = 100;
static char arquivoEntrada[50] = "h:\\public_html\\tg\\testes\\out\\visualize.xyz";

typedef struct _float{
  float valor;
  struct _float *next;
} Float;

typedef struct atomo {
  char simbolo[2];
	float coordX;
	float coordY;
	float coordZ;
	Float *dados;
	struct atomo *prev;
	struct atomo *next;
} Atomo;

/***********************************************
Variáveis globais para as listas encadeadas
************************************************/
Atomo *listaAtomos = NULL, *atualAtomo = NULL;
Float *floats = NULL, *atualFloat = NULL;

/***********************************************
Assinatura das funções
************************************************/
void lerArquivoXYZ(FILE *in);
void escreverDadosXYZ();
void inserirAtomo(Atomo *atomo_new);
void inserirFloat(Float *float_new);
void desalocaAtomo(Atomo **atual);
void desalocaFloat(Float **listaFloats);
void limpar();

void acharLigacoes();
float distancia(Atomo atomo1, Atomo atomo2);
float sqr(float valor);


/***********************************************
Funções para leitura do arquivo
************************************************/
void lerArquivoXYZ(FILE *in){

	int i = 0, numLinhas = 0;
	int jaLeuSoluto = 0;
	char texto[100] = "";
	float potencial;

	if (!(in=fopen(arquivoEntrada,"r+"))){
		printf ("\nErro na abertura do arquivo de entrada!");
		getch();
		exit(1);
	}

	fscanf(in, "%d\n", &numLinhas);
    fgets(texto, 100, in);


	while (i < numLinhas) {

	  Atomo *atomo_new = (Atomo *) malloc (sizeof(Atomo));
      if (!jaLeuSoluto) {
        fscanf (in,"%s %f %f %f",&(atomo_new->simbolo),
								 &(atomo_new->coordX),
								 &(atomo_new->coordY),
								 &(atomo_new->coordZ));

        floats = NULL;
		while (fscanf(in, "%f", &potencial)) {
          Float *float_new = (Float *) malloc (sizeof(Float));
		  float_new->valor = potencial;
		  if (floats) {
		    inserirFloat(float_new);
		  } else {
            float_new->next = NULL;
            floats = atualFloat = float_new;
		  }
		}
	    atomo_new->dados = floats;
		if (listaAtomos) {
	      inserirAtomo(atomo_new);
		} else {
		  listaAtomos = atualAtomo = atomo_new;
          atomo_new->next = NULL;
          atomo_new->prev = NULL;
		}
	    i++;
	  }
	}
	fclose(in);
}


/*************************************************
Armazenamento com lista encandeada
*************************************************/

void inserirAtomo(Atomo *atomo_new){
    atomo_new->next = NULL;
	atomo_new->prev = atualAtomo;
    atualAtomo->next = atomo_new;
	atualAtomo = atomo_new;
}


void inserirFloat(Float *float_new) {
    float_new->next = NULL;
    atualFloat->next = float_new;
	atualFloat = float_new;
}

void limpar(){
	desalocaAtomo(&atualAtomo);
}

void desalocaAtomo(Atomo **atual){
    Atomo *aux;
	while ((*atual)->prev){
		aux = (*atual)->prev;
		aux->next = NULL;
		if ((*atual)->dados) {
		    desalocaFloat(&((*atual)->dados));
		}
		free(*atual);
		*atual = aux;
	}
	free(*atual);
	*atual = NULL;
}

void desalocaFloat(Float **listaFloats){
    Float *aux;
	while ((*listaFloats)->next){ 
		aux = (*listaFloats)->next;
		(*listaFloats)->next = aux->next;
		free(aux);
	}
	free(*listaFloats);
	*listaFloats = NULL;
}

/***********************************************
Funções para processamento dos dados
************************************************/

/***********************************************
Achar os atomos que tem ligações
************************************************/
void acharLigacoes(){

	Atomo *aux = listaAtomos;
	while (aux->next && !aux->dados){
		Atomo *aux2 = listaAtomos;
		while (aux2->next && !aux2->dados){
			float dist = distancia(*aux, *aux2);
			if (aux != aux2 &&  dist < 1.94){ 
				printf("%s - %s: %.3f\n",aux->simbolo, aux2->simbolo, dist);
			} else {
			    printf("> %s - %s: %.3f\n",aux->simbolo, aux2->simbolo, dist);
			}
			aux2 = aux2->next;
		}
		aux = aux->next;
	}
}

float distancia(Atomo atomo1, Atomo atomo2){
	return (float) sqrt(
		      sqr1(atomo1.coordX - atomo2.coordX) +
              sqr1(atomo1.coordY - atomo2.coordY) +
		      sqr1(atomo1.coordZ - atomo2.coordZ));
}

float sqr(float valor){
    return valor*valor;
}