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

package vut.msa.managedBeans;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.faces.event.ActionEvent;
import org.apache.log4j.Logger;
import org.hyperic.sigar.DirUsage;
import org.hyperic.sigar.FileSystem;
import org.hyperic.sigar.FileSystemUsage;
import org.hyperic.sigar.SigarException;
import vut.msa.exceptions.FacesException;
import vut.msa.helpers.BackupDiskHelper;
import vut.msa.helpers.ClientHelper;
import vut.msa.monitor.system.FileSystemCompleteInfo;
import vut.msa.monitor.system.ServerInformation;
import vut.msa.pojos.BackupDisk;
import vut.msa.utilities.FileUtilities;

/**
 * JavaBean pre informacie o diskoch.
 */
public class DisksBean {

    private static final Logger log = Logger.getLogger(DisksBean.class);
    
    private List<FileSystemCompleteInfo> connectedDisks;
    private FileSystem selectedFileSystem;

    private BackupDiskHelper helper;
    private ClientHelper cHelper;

    public DisksBean() {
        reloadData();
        helper = new BackupDiskHelper();
        cHelper = new ClientHelper();
    }

    //PROPERTY: connectedDisks
    public List<FileSystemCompleteInfo> getConnectedDisks() { return connectedDisks; }
    public void setConnectedDisks(List<FileSystemCompleteInfo> connectedDisks) {
        this.connectedDisks = connectedDisks;
    }

    //PROPERTY: selectedFileSystem
    public FileSystem getSelectedFileSystem() { return selectedFileSystem; }
    public void setSelectedFileSystem(FileSystem selectedFileSystem) {
        this.selectedFileSystem = selectedFileSystem;
    }

    /**
     * Metoda sluzina vytvorenie adresara backup pre zalohy na zvolenom disku.
     * Tuto metodu vola uzivatelske rozhranie po stlaceni tlacidla.
     * Metoda po vytvoreni adresara na disku, vytvory zaznam aj v databaze.
     *
     * @param event udalost stlacenia tlacidla na JSF stranke
     */
    public void activeBackupDrive(ActionEvent event) {

        try {
            String diskPath = (String)event.getComponent().getAttributes().get("drive");

            File mkDir = new File (diskPath
                                    + "backup");
            if (!mkDir.exists()) {
                boolean success = mkDir.mkdir();

                if (success) {
                    helper.addBackupDisk(new BackupDisk(diskPath));
                    log.info("Vytvorenie adresara pre zalohy sa podarilo.");
                }
            }
            
            reloadData();
        } catch (Exception ex) {
            log.error("Vytvorenie adresara pre zalohy sa nepodarilo.");
        }
    }

    /**
     * Metoda zrusi pouzivanie ulozneho media pre ukladanie zaloh. V pripade, ze
     * sa jednotka pouzivala, udaje su prekopirovane na iny disk. Vyberie sa ten, ktory
     * je najmenej zaplneny. Ak nie je mozno udaje inam prekopirovat, metoda
     * nevykona nic a chybu oznami uzivatelovi.
     *
     * @param event udalost stlacenia tlacidla pre deaktivaciu uloz. media
     */
    public void deactivateBackupDrive(ActionEvent event) {

        try {
            String diskPath = (String)event.getComponent().getAttributes().get("drive");

            File delDir = new File (diskPath
                                    + "backup");
            if (delDir.exists()) {
                Iterator<FileSystemCompleteInfo> iterator = connectedDisks.iterator();
                double maxFree = 0;
                String bestDisk = null;
                while (iterator.hasNext()) {
                    FileSystemCompleteInfo fsci = iterator.next();
                    if (fsci.isUsedForBackup()) {
                        double free = (new Long(fsci.getFsUsage().getFree()).doubleValue())/(new Long(fsci.getFsUsage().getTotal()).doubleValue());
                        if (!diskPath.equals(fsci.getFileSystem().getDevName()) && free > maxFree) {
                            maxFree = free;
                            bestDisk = fsci.getFileSystem().getDevName();
                        }
                    }
                }

                if (bestDisk == null) {
                    throw new FacesException("Disk nemôže byť vypnutý.",
                                "Zálohy nie je kam presunúť.");
                }

                boolean success = false;

                log.info("Vybrany disk " + bestDisk + " pre presun zaloh.");
                if (bestDisk != null) {
                    cHelper.changeBackupDiskForClients(diskPath, bestDisk);
                    File bestDir = new File (bestDisk
                                        + "backup");
                    FileUtilities.copyFolder(delDir, bestDir);
                    success = FileUtilities.deleteDirectory(delDir);
                }
                if (success) {
                    helper.removeBackupDisk(new BackupDisk(diskPath));
                    log.info("Zmazanie adresara pre zalohy sa podarilo.");
                }
            }

            reloadData();
        } catch (Exception ex) {
            log.error("Zmazanie adresara pre zalohy sa nepodarilo.");
        }
    }

    /**
     * Metoda nacita udaje do premennych triedy.
     */
    private void reloadData() {
        /* Ako zalohovacie mozem pouzit len zapisovatelne. Opticke media sa v tomto
         * momente nepouzivaju.
         */
        ServerInformation info = ServerInformation.getInstance();
        List<FileSystem> temporary = info.getFsList();
        connectedDisks = new ArrayList<FileSystemCompleteInfo>();
        Iterator<FileSystem> iterator = temporary.iterator();
        while(iterator.hasNext()) {
            FileSystem fs = iterator.next();
            if (fs.getOptions().equals("rw")) {
                try {
                    FileSystemUsage fsUsage = info.getSigar().getFileSystemUsage(fs.getDevName());

                    DirUsage dUsage = new DirUsage();

                    boolean usedForBackup;
                    try {
                        dUsage = info.getSigar().getDirUsage(fs.getDirName()
                                        + "backup" );
                        log.info(dUsage.toString());
                        usedForBackup = true;
                    } catch (Exception ex) {
                        log.error("Nepodarilo sa ziskat informacie o adresari.");
                        usedForBackup = false;
                    }

                    FileSystemCompleteInfo fsci =
                            new FileSystemCompleteInfo(fs, fsUsage, dUsage);
                    fsci.setUsedForBackup(usedForBackup);
                    log.info("Pouziva sa?" + usedForBackup);
                    connectedDisks.add(fsci);
                } catch (SigarException ex) {
                    log.error("Chyba pri vytvranani zoznamu informacii o diskoch.");
                }
            }
        }
    }

}
