/*
 * StoragePoolResource.java
 * 
 * Copyright (c) 2009 Olocity Corporation. All rights reserved.
 * 
 * This file is part of the StorageIM Application.
 * 
 * StorageIM Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * StorageIM Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with StorageIM.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.olocity.rest.resources;

import java.net.URI;
import java.util.Iterator;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.storageim.util.HibernateUtil;

@Path("/master")
public class StoragePoolsResource {
	
	private Logger logger;
	private Session session = null;
	private String CN = "StoragePoolResource";
	
	java.text.DecimalFormat df = new java.text.DecimalFormat("###.##");

	public StoragePoolsResource() {
		logger = Logger.getLogger(CN);
	}
	
	/**
	 * Returns basic capabilities
	 */
	@GET
	@Path("cdmi_capabilities")
    @Produces({"application/vnd.org.snia.cdmi.capabilities+json", "text/plain"})
	//@Produces({"text/plain"})
    public String getAccountCapabilities() {
		String capabilities = "\"name\" : \"cdmi_capabilities, uri\" : \"/master/cdmi/cdmi_capabilities\" ,\"capabilities\" : [ \"cdmi_list\"]";
    	return capabilities;
    }

    /**
     * Returns a Response of primordial CIM_StoragePools
     */
    @GET 
    @Produces({"application/vnd.org.snia.cdmi.container+json", "text/plain"})
    //@Produces({"text/plain"})
    public Response getStoragePools() {
    	String instanceId = "";
    	String instanceIds = "";
    	Long totalManagedSpace;
		Long unassigned;
		Long assigned;
		Long assignedTotal;
		String name = "name: cdmi";
		String data = "InstanceID, Assigned, Unassigned, TotalManagedSpace";
		/* 
		 * TODO <KEK> Change this to dynamic URI.
		 */
		String uri = "uri: http://localhost:8081/storageim/cdmi/master/";
		
		unassigned = 0L;
		assigned = 0L;
		totalManagedSpace = 0L;
		assignedTotal = 0L;
		
		session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
		
		String sqlArrayCapacity = "SELECT DISTINCT csp.instanceId, csp.totalManagedSpace, csp.remainingManagedSpace, csp.primordial " +
		"FROM cim_computersystem ccs " +
		"Inner Join cimomflag cf ON ccs.cimomID = cf.cimomID " +
		"Inner Join cim_hostedstoragepool chsp ON ccs.computerSystemID = chsp.computerSystemID " +
		"Inner Join cim_storagepool csp ON chsp.storagePoolID = csp.storagePoolID " +
		"WHERE timeOfCreation = (SELECT MAX(timeOfCreation) FROM cim_computersystem i2 WHERE i2.name=ccs.name ) AND cf.deletion =  '0' and csp.primordial='t'";

		Iterator<?> i = session.createSQLQuery(sqlArrayCapacity).list().iterator();

		while (i.hasNext()) {
			 
			Object[] row = (Object[]) i.next();
			try {
				instanceId = row[0].toString();
				logger.info("InstanceID value " + i + " = " + instanceId);
			} catch (Exception e) {
				
			}
			try {
				logger.debug("assigned val before = " + assigned);
				assigned = (Long.valueOf(row[1].toString()).longValue() - Long.valueOf(row[2].toString()).longValue());
				logger.debug("Assigned value " + i + " = " + assigned);
			} catch (Exception e) {
				
			}
			try {
				logger.debug("unassigned val before = " + unassigned);
				unassigned = Long.valueOf(row[2].toString()).longValue();
				logger.debug("Unassigned value " + i + " = " + unassigned);
			} catch (Exception e) {
				
			}
			try {
				logger.debug("TMS val before = " + totalManagedSpace);
				totalManagedSpace = Long.valueOf(row[1].toString()).longValue();
				logger.debug("TMS value " + i + " = " + totalManagedSpace);
			} catch (Exception e) {
				
			}
			assignedTotal = assignedTotal + assigned;
			data = data + "\n" + uri + "\n" + totalManagedSpace;
			instanceIds = instanceIds + instanceId+",";
		}
		
		instanceIds = instanceIds.substring(0, instanceIds.length()-1);
		
		session.flush();
		session.close();

		String finalData =  name + "\n" + uri + "\n" + "metadata: " + "[cdmi_size = " + assignedTotal+"]" + "\n" + "children: [" + instanceIds + "]";
		return Response.created(URI.create("http://localhost:8081/storageim/cdmi/master/")).entity(finalData).build();
    }
    
    /**
     * Returns a list of concrete CIM_StoragePools based on input primoridial storage pool
     * @param id
     * @return
     */
    @GET 
    @Path("{id}/")
    @Produces({"application/vnd.org.snia.cdmi.container+json", "text/plain"})
    //@Produces({"text/plain"})
    public Response getContainer(@PathParam("id") String id) {
    	String uri = "http://localhost:8081/storageim/cdmi/master/"+id;
    	logger.info(id);
    	String response = null;

    	
    	String instanceId = "";
    	String instanceIds = "";
    	Long totalManagedSpace;
		Long unassigned;
		Long assigned;
		Long assignedTotal;
		
		unassigned = 0L;
		assigned = 0L;
		assignedTotal = 0L;
		totalManagedSpace = 0L;

		session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
		
		String sqlArrayCapacity = "SELECT DISTINCT csp.instanceId, csp.totalManagedSpace, csp.remainingManagedSpace, csp.primordial " +
		"FROM cim_computersystem ccs " +
		"Inner Join cimomflag cf ON ccs.cimomID = cf.cimomID " +
		"Inner Join cim_hostedstoragepool chsp ON ccs.computerSystemID = chsp.computerSystemID " +
		"Inner Join cim_storagepool csp ON chsp.storagePoolID = csp.storagePoolID " +
		"WHERE timeOfCreation = (SELECT MAX(timeOfCreation) FROM cim_computersystem i2 WHERE i2.name=ccs.name ) AND cf.deletion =  '0' and csp.allocatedFromStoragePool='"+id+"'";

		Iterator<?> i = session.createSQLQuery(sqlArrayCapacity).list().iterator();
		//DashboardCapacity dc = null;

		//dc = new DashboardCapacity();
		while (i.hasNext()) {
			 
			Object[] row = (Object[]) i.next();
			try {
				instanceId = row[0].toString();
				logger.info("InstanceID value " + i + " = " + instanceId);
			} catch (Exception e) {
				
			}
			try {
				logger.debug("assigned val before = " + assigned);
				assigned = (Long.valueOf(row[1].toString()).longValue() - Long.valueOf(row[2].toString()).longValue());
				logger.debug("Assigned value " + i + " = " + assigned);
			} catch (Exception e) {
				
			}
			try {
				logger.debug("unassigned val before = " + unassigned);
				unassigned = Long.valueOf(row[2].toString()).longValue();
				logger.debug("Unassigned value " + i + " = " + unassigned);
			} catch (Exception e) {
				
			}
			try {
				logger.debug("TMS val before = " + totalManagedSpace);
				totalManagedSpace = Long.valueOf(row[1].toString()).longValue();
				logger.debug("TMS value " + i + " = " + totalManagedSpace);
			} catch (Exception e) {
				
			}
			instanceIds = instanceIds + instanceId+",";
			assignedTotal = assignedTotal + assigned;
		}
		
		instanceIds = instanceIds.substring(0, instanceIds.length()-1);
		
		session.flush();
		session.close();

   		response = "name: " + id + "\n" + "uri: " + uri + "\n" + "metadata: [cdmi_size : " + assignedTotal + "]\n" + "children: [" + instanceIds + "]";
    	return Response.created(URI.create(uri)).entity(response).build();
    }
    
    /**
     * Returns all storage volumes that are associated to a concrete pool and associated primordial pool
     * @param id
     * @param id1
     * @return
     */
    @GET 
    @Path("{id}/{id1}")
    @Produces({"application/vnd.org.snia.cdmi.container+json", "text/plain"})
    //@Produces({"text/plain"})
    public Response getContainer2(@PathParam("id") String id, @PathParam("id1") String id1) {
    	String uri = "http://localhost:8081/storageim/cdmi/master/"+id+"/"+id1;
    	logger.info(id);

    	String response = null;

    	String deviceIds = "";
    	
    	String volumeDeviceId;
    	String volumeName;
    	String volumeExtentStatus;
    	String volumeOperationalStatus;
    	Long volumeBlockSize;
    	Long volumeNumberOfBlocks;
    	Long volumeConsumableBlocks;
    	String instancePropertySizeLUN;
    	String volumePoolInstanceId;
    	Long volumePoolRemainingManagedSpace=0l;
    	Long volumePoolTotalManagedSpace=0l;

		session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
		
		String sqlArrayCapacity = "SELECT csv.deviceId, csv.name, csv.extentStatus, csv.operationalStatus, csv.blockSize, csv.numberOfBlocks, csv.consumableBlocks, csv.noSinglePointOfFailure, csv.dataRedundancy, csv.deltaReservation, csv.packageRedundancy, csv.instanceTimeMean, csv.instancePropertySize, csp.instanceId, csp.remainingManagedSpace, csp.totalManagedSpace " +
			"FROM cim_computersystem ccs " +
			"Inner Join cimomflag cf ON ccs.cimomID = cf.cimomID " +
			"Inner Join cim_hostedstoragepool chsp ON ccs.computerSystemID = chsp.computerSystemID  " +
			"Inner Join cim_storagepool csp ON chsp.storagePoolID = csp.storagePoolID  " +
			"Inner Join cim_allocatedfromstoragepool cafsp ON csp.storagePoolID = cafsp.storagePoolID  " +
			"Inner Join cim_storagevolume csv ON cafsp.storageVolumeID = csv.storageVolumeID  " +
			"WHERE timeOfCreation = (SELECT MAX(timeOfCreation) FROM cim_computersystem i2 WHERE i2.name=ccs.name ) AND cf.deletion =  '0' and csp.instanceId like '"+id1+"'";
		Iterator<?> i = session.createSQLQuery(sqlArrayCapacity).list().iterator();
		if (i.hasNext()){
			while (i.hasNext()) {
				
				Object[] row = (Object[]) i.next();
				
				volumeDeviceId = row[0].toString();
				volumeName = row[1].toString();
				try {
					volumeExtentStatus = row[2].toString();
				} catch (NullPointerException ne) {
					volumeExtentStatus = null;
				}
				volumeOperationalStatus = row[3].toString();
				volumeBlockSize = Long.valueOf(row[4].toString()).longValue();
				volumeNumberOfBlocks = Long.valueOf(row[5].toString()).longValue();
				try {
				volumeConsumableBlocks = Long.valueOf(row[6].toString()).longValue();
				} catch (NullPointerException npe) {
					volumeConsumableBlocks = null;
				}

				try {
					instancePropertySizeLUN = row[12].toString();
				} catch (NullPointerException e) {
					instancePropertySizeLUN = "Not Available";
				}
				try {
					volumePoolInstanceId = row[13].toString();
				} catch (NullPointerException e) {
					volumePoolInstanceId = "Not Available";
				}
				try {
					volumePoolRemainingManagedSpace = Long.valueOf(row[14].toString()).longValue();
				} catch (NullPointerException e) {
					volumePoolRemainingManagedSpace = 0L;
				}
				try {
					volumePoolTotalManagedSpace = Long.valueOf(row[15].toString()).longValue();
				} catch (NullPointerException e) {
					volumePoolTotalManagedSpace = 0L;
				}
		
				
				logger.info(volumeDeviceId);
				logger.info(volumeName);
				logger.info(volumeExtentStatus);
				logger.info(volumeOperationalStatus);
				logger.info(volumeBlockSize);
				logger.info(volumeNumberOfBlocks);
				logger.info(volumeConsumableBlocks);				
				logger.info(instancePropertySizeLUN);
				logger.info(volumePoolInstanceId);
				logger.info(volumePoolRemainingManagedSpace);
				logger.info(volumePoolTotalManagedSpace);
				
				deviceIds = deviceIds + volumeDeviceId+",";
			}
		}
		deviceIds = deviceIds.substring(0, deviceIds.length()-1);
		Long AllocatedSpace = volumePoolTotalManagedSpace - volumePoolRemainingManagedSpace;
		session.flush();
		session.close();
				

   		response = "name: " + id + "\n" + "uri: " + uri + "\n" + "metadata: [cdmi_size : " + AllocatedSpace + "]\n" + "children: [" + deviceIds + "]";
    	return Response.created(URI.create(uri)).entity(response).build();
    }
}