package com.henrypump.poc;

/**
 * Created by patrickjmcd on 2/2/17.
 */

import com.mongodb.*;

import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoCollection;

import com.mongodb.client.model.Sorts;
import org.bson.Document;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Arrays;

import com.mongodb.client.MongoCursor;

import static com.mongodb.client.model.Aggregates.limit;
import static com.mongodb.client.model.Filters.*;
import com.mongodb.client.result.DeleteResult;
import static com.mongodb.client.model.Updates.*;
import com.mongodb.client.result.UpdateResult;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Database {
    private String pocDatabase = "poc";
    private MongoClient mongoClient;
    private MongoDatabase database;

    Database(){
        mongoClient = new MongoClient();
        database = mongoClient.getDatabase(pocDatabase);
    }

    public long getLastStrokeNum(){
        MongoCollection<Document> collection = database.getCollection("cards");
        MongoCursor<Document> cursor = collection.find().iterator();
        long lastStroke = 0;
        try {
            while (cursor.hasNext()) {
                long docStroke = (Long) cursor.next().get("strokeNumber");
                if (docStroke  > lastStroke) { lastStroke = docStroke; }
            }
        } finally {
            cursor.close();
        }
        return lastStroke;
    }

    public long newCard(Card inpCard){
        MongoCollection<Document> collection = database.getCollection("cards");
        List<Double> s_p = new ArrayList<Double>();
        List<Double> s_l = new ArrayList<Double>();
        List<Double> d_p = new ArrayList<Double>();
        List<Double> d_l = new ArrayList<Double>();
        int numPointsScan = inpCard.getNumPointsUsed();
        double[] sp = inpCard.getSurfacePosition();
        double[] sl = inpCard.getSurfaceLoad();
        double[] dp = inpCard.getDownholePosition();
        double[] dl = inpCard.getDownholeLoad();
        for(int i = 0; i < numPointsScan; i++ ) {
            s_p.add(sp[i]);
            s_l.add(sl[i]);
            d_p.add(dp[i]);
            d_l.add(dl[i]);
        }

        Document doc = new Document("strokeNumber", inpCard.getStrokeNumber())
                .append("surface_position", s_p)
                .append("surface_load", s_l)
                .append("downhole_position", d_p)
                .append("downhole_load", d_l);
        collection.insertOne(doc);
        return collection.count();
    }
    public void close(){
        mongoClient.close();
    }

    public long newMeasurement(Measurement inpMeasurement){
        String df = Date.from(Instant.now()).toString();
        MongoCollection<Document> collection = database.getCollection("wellData");
        Document doc = new Document("tagname", inpMeasurement.getTagName())
                .append("currentValue", inpMeasurement.getCurrentValue())
                .append("maxDailyValue", inpMeasurement.getDailyMax())
                .append("minDailyValue", inpMeasurement.getDailyMin())
                .append("dailyAverage", inpMeasurement.getAverage())
                .append("dailyTotal", inpMeasurement.getTotal())
                .append("timestamp", df);
        collection.insertOne(doc);
        return collection.count();
    }

    public long newDailyTotal(Measurement inpMeasurement){
        String df = Date.from(Instant.now()).toString();
        MongoCollection<Document> collection = database.getCollection("gaugeOffData");
        Document doc = new Document("tagname", inpMeasurement.getTagName())
                .append("currentValue", inpMeasurement.getCurrentValue())
                .append("maxDailyValue", inpMeasurement.getDailyMax())
                .append("minDailyValue", inpMeasurement.getDailyMin())
                .append("dailyAverage", inpMeasurement.getAverage())
                .append("dailyTotal", inpMeasurement.getTotal())
                .append("timestamp", df);
        collection.insertOne(doc);
        return collection.count();

    }

    public double getPreviousDailyTotal(Date inpDateTime){
        String isoInpDateTime = inpDateTime.toString();
        MongoCollection<Document> wellTestCollection = database.getCollection("gaugeOffData");
        MongoCursor<Document> cursor = wellTestCollection.find(and(eq("tagname", "Fluid Produced"), lte("timestamp", isoInpDateTime)))
                .sort(Sorts.descending("timestamp")).limit(1).iterator();
        double lastTotal = -1.0;
        try {
            while (cursor.hasNext()) {
                lastTotal = cursor.next().getDouble("dailyTotal");
            }
        } finally {
            cursor.close();
        }
        return lastTotal;
    };

    public long newWellTest(WellTest inp){
        String df = Date.from(Instant.now()).toString();
        MongoCollection<Document> collection = database.getCollection("wellTestData");
        Document doc = new Document("testStartTime", df)
                .append("testHours", inp.getTestHours())
                .append("testTotalBBL", inp.getTotalFluidBBL())
                .append("testOilBBL", inp.getTestOilBBL())
                .append("testWaterBBL", inp.getTestWaterBBL())
                .append("testGasMCF", inp.getTestGasMCF())
                .append("kFactor", inp.getkFactor())
                .append("oilRatio", inp.getOilRatio())
                .append("waterRatio", inp.getWaterRatio())
                .append("gasMCFRatio", inp.getGasMCFRatio());
        collection.insertOne(doc);
        return collection.count();
    }

    public Document getPreviousWellTest(Date inpDateTime){
        String isoInpDateTime = inpDateTime.toString();
        MongoCollection<Document> wellTestCollection = database.getCollection("wellTestData");
        MongoCursor<Document> cursor = wellTestCollection.find(lte("testStartTime", isoInpDateTime))
                .sort(Sorts.descending("testStartTime")).limit(1).iterator();
        Document lastTest = new Document("kFactor", (Double) 1.0);
        try {
            while (cursor.hasNext()) {
                lastTest = cursor.next();
            }
        } finally {
            cursor.close();
        }
        return lastTest;
    };

    public double getLatestKFactor(){
        MongoCollection<Document> wellTestCollection = database.getCollection("wellTestData");
        MongoCursor<Document> cursor = wellTestCollection.find().sort(Sorts.descending("testStartTime")).limit(1).iterator();
        double kFactor = 1.0;
        try {
            while (cursor.hasNext()) {
                kFactor = cursor.next().getDouble("kFactor");
            }
        } finally {
            cursor.close();
        }
        return kFactor;
    }

}
