/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pnandmd.Point3;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *Klasa która dostaje na wejscie pliki z nazwami miejsc, trnazycji, siecia oraz marking.
 * Tworzy na ich podstawie plik pdb zawierajacy CA atomy polaczone.
 * Zakladamy ze pliki maja domysle nazwy i sa w folderze projektu.
 * 
 * @author Ania
 */
public class TworzPDB {
    
    
     //do czytania plikow z nazwami miejsc - zczytuje wspolrzedne do macierzy
    private BufferedReader mNazwy;
    //do czytania pliku z markingiem
    private BufferedReader mPlik;
    //przechowuje marking
    private int[] marking;
    //przechowuje informacje o miejscach, indeks w tablicy to nr miejsca,
    //pierwsza wsp to nr atomu, kolejne to x, y, z
    private double[][] miejsca;
    //ile pierwszych miejsc jest bez wspolrzednych, polowa z nich to miejsca-atomy
    //a druga to miejsca startowe
    private int przes;
    //ilosc miejsc
    private int lmiejsc = 0;
    //jakie dlugosci maja macierze ze "wspolrzednymi" - atom + x,y,z
    private int dl = 4;
    
    
    /**
     * Czyta pliki z informacjami o miejsach i markingu.
     * Dane wpisuje do odpowiednich macierzy.
     */
    public TworzPDB(){
        try {
            mNazwy = new BufferedReader(new FileReader("mNazwy.txt"));
            
            BufferedReader wyst = new BufferedReader(new FileReader("wystapienia.txt"));
            String linia = wyst.readLine();
            String[] tab = linia.split(" ");
            lmiejsc = Integer.parseInt(tab[3]);
            lmiejsc++;
            miejsca = new double[lmiejsc][dl];
            czytajMiejsca();
            mNazwy.close();
            
            marking = new int[lmiejsc];
            czytajMarking();
            
            
        } catch (IOException ex) {
            Logger.getLogger(TworzPDB.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Czyta informacje o miejscach z pliku - ich wspolrzedne i dla ktorego atomu
     * Wpisuje to do odpowiedniej macierzy.
     */
    private void czytajMiejsca(){
        try {
            String linia;
            String [] tab;
            String [] tab2;
            double[] wsp = new double[4];
            boolean pierw = true;
            int a, p;
            while ((linia = mNazwy.readLine()) != null) {
                
                tab = linia.split(" ");
                p = Integer.parseInt(tab[1]);
                a = Integer.parseInt(tab[4]);
                if(pierw == true){
                    przes = p - a;
                    pierw = false;
                }
                wsp[0] = 1.0 * a;
                tab2 = tab[6].split(",");
                wsp[1] = Double.parseDouble(tab2[0]);
                wsp[2] = Double.parseDouble(tab2[1]);
                wsp[3] = Double.parseDouble(tab2[2]);
                przepiszMiejsca(p, wsp);
            }
            /*for(int i = 0; i < lmiejsc; i++){
                System.out.println("nr: "+i+" atom: "+miejsca[i][0]+" wsp: "+miejsca[i][1]+", "+miejsca[i][2]+", "+miejsca[i][3]);
            }*/
        } catch (IOException ex) {
            Logger.getLogger(TworzPDB.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Wczytuje do pamieci marking z pliku marking.txt.
     */
    public final void czytajMarking(){
        try {
            mPlik = new BufferedReader(new FileReader("marking.txt"));
            String linia;
            linia = mPlik.readLine();
            String[] tab = linia.split(" ");
            int n = tab.length;
            for(int i = 0; i < n; i++){
                marking[i] = Integer.parseInt(tab[i]);
            }
            mPlik.close();
        } catch (IOException ex) {
            Logger.getLogger(TworzPDB.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Wczytuje marking z pliku ktorego nazwa podana jako argument.
     * @param file nazwa pliku z markingiem
     */
    public final void czytajMarking(String file){
        try {
            mPlik = new BufferedReader(new FileReader(file));
            String linia;
            linia = mPlik.readLine();
            String[] tab = linia.split(" ");
            int n = tab.length;
            for(int i = 0; i < n; i++){
                marking[i] = Integer.parseInt(tab[i]);
            }
            mPlik.close();
        } catch (IOException ex) {
            Logger.getLogger(TworzPDB.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Przepisuje informacje z tablicy tab do macierzy miejsca do indeksu nr.
     * @param nr indeks pod ktory wpisac informacje z malej tablicy
     * @param tab mala tablica do wpisania do miejsca
     */
    private void przepiszMiejsca(int nr, double[] tab){
        System.arraycopy(tab, 0, miejsca[nr], 0, dl);
    }
    
    /**
     * Tworzy plik pdb na postawie wczytajen podczas tworzenia obiektu sieci
     * i wczytanego markingu.
     */
    public void generujPdb(){
        BufferedWriter pdb = null;
        int index;
        String linia, pom;
        char[] czesc;
        try {
            int atomy = przes / 2;
            pdb = new BufferedWriter(new FileWriter("poSieci.pdb"));
            for(int i = 0; i < atomy; i++){
                linia = "";
                index = przes + 1;
                
                while(!((miejsca[index][0] == (1.0 * i))  && (marking[index] == 1))){
                    index ++;
                }
                            
                czesc = new char[6];
                pom = "ATOM  ";
                linia = pomocnicza(linia, czesc, pom);
                czesc = new char[5];
                pom = Integer.toString(i);
                linia = pomocnicza(linia, czesc, pom);
                linia = linia + " ";
                czesc = new char[4];
                pom = "O";
                linia = pomocnicza(linia, czesc, pom);
                linia = linia + " ";
                czesc = new char[3];
                pom = "VAL";
                linia = pomocnicza(linia, czesc, pom);
                linia = linia + " A";
                czesc = new char[4];
                pom = Integer.toString(i);
                linia = pomocnicza(linia, czesc, pom);
                linia = linia + "    ";
                czesc = new char[8];
                pom = Double.toString(miejsca[index][1]);
                linia = pomocnicza(linia, czesc, pom);
                czesc = new char[8];
                pom = Double.toString(miejsca[index][2]);
                linia = pomocnicza(linia, czesc, pom);
                czesc = new char[8];
                pom = Double.toString(miejsca[index][3]);
                linia = pomocnicza(linia, czesc, pom);
                czesc = new char[6];
                pom = "1.00";
                linia = pomocnicza(linia, czesc, pom);
                czesc = new char[6];
                pom = "0.00";
                linia = pomocnicza(linia, czesc, pom);
                linia = linia + "      ";
                czesc = new char[4];
                pom = "A";
                czesc = wpiszLewa(czesc, pom);
                linia = linia + new String(czesc);
                linia = linia + "    ";

                pdb.write(linia);
                pdb.newLine();
                
            }
            for(int i = 0; i < atomy - 1; i++){
                linia = "CONECT ";
                czesc = new char[4];
                pom = Integer.toString(i);
                czesc = wpiszLewa(czesc, pom);
                linia = linia + new String(czesc);
                
                czesc = new char[5];
                pom = Integer.toString(i + 1);
                czesc = wpiszLewa(czesc, pom);
                linia = linia + new String(czesc);
                
                for(int j = 0; j < 15; j++){
                    linia = linia + " ";
                }
                
                pdb.write(linia);
                pdb.newLine();
            }
            
            
        } catch (IOException ex) {
            Logger.getLogger(TworzPDB.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                pdb.close();
            } catch (IOException ex) {
                Logger.getLogger(TworzPDB.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    /**
     * Wpisuje tekst ze stringa do tablicy znakow na jej koniec - tzn wyrownanie do prawej
     * @param tab tablica do kotrej wpisuje tekst
     * @param tekst tekst do wpisania
     * @return tablica z wpisanym tekstem
     */
    private char[] wpisz(char[] tab, String tekst){
        int n = tab.length;
        int m = tekst.length();
        int i, j;
        for(i = n - 1, j = m - 1; i >= 0; i--, j--){
            if(j >= 0) {
                tab[i] = tekst.charAt(j);
            }
            else{
                tab[i] = ' ';
            }
        }
        return tab;
    }
    
    /**
     * to co wyzej ale wpisuje wyrownujac do lewej
     * @param tab
     * @param tekst
     * @return 
     */
    private char[] wpiszLewa(char[] tab, String tekst){
        int n = tab.length;
        int m = tekst.length();
        int i, j;
        for(i = 0, j = 0; i < n; i++, j++){
            if(j < m){
                tab[i] = tekst.charAt(j);
            }
            else{
                tab[i] = ' ';
            }
        }
        
        return tab;
    }
    
    /**
     * Dopisuje tablice tab do stringa linia, ktorego zwraca.
     * @param linia
     * @param tab
     * @return 
     */
    private String pomocnicza(String linia, char[] tab, String pom){
        tab = wpisz(tab, pom);
        linia = linia + new String(tab);
        return linia;
    }
    
}
