# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2010-2011, GEM Foundation.
#
# OpenQuake is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# only, as published by the Free Software Foundation.
#
# OpenQuake 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 Lesser General Public License version 3 for more details
# (a copy is included in the LICENSE file that accompanied this code).
#
# You should have received a copy of the GNU Lesser General Public License
# version 3 along with OpenQuake.  If not, see
# <http://www.gnu.org/licenses/lgpl-3.0.txt> for a copy of the LGPLv3 License.

import os
import unittest
import geohash
import numpy

from nose.plugins.attrib import attr

from openquake.db import models
from openquake import shapes
from tests.utils import helpers


class ClassicalPSHACalculatorAssuranceTestCase(
    unittest.TestCase, helpers.DbTestMixin):

    @attr("quality_assurance")
    def test_peerTestSet1Case2(self):
        expected_results = self._load_results("PeerTestSet1Case2")

        job = self._run_job(helpers.smoketest_file(
            os.path.join("PeerTestSet1Case2", "config.gem")))

        self._compare_results_for(job, expected_results)

    @attr("quality_assurance")
    def test_peerTestSet1Case5(self):
        expected_results = self._load_results("PeerTestSet1Case5")

        job = self._run_job(helpers.smoketest_file(
            os.path.join("PeerTestSet1Case5", "config.gem")))

        self._compare_results_for(job, expected_results)

    def _compare_results_for(self, job, expected_results):
        """Compare the expected results with the results
        computed by the given job."""

        job_db = models.OqJob.objects.get(id=job.job_id)

        for site, curve in expected_results.items():
            gh = geohash.encode(site.latitude, site.longitude, precision=12)

            hc_db = models.HazardCurveData.objects.filter(
                hazard_curve__output__oq_job=job_db,
                hazard_curve__statistic_type="mean").extra(
                where=["ST_GeoHash(location, 12) = %s"], params=[gh]).get()

            self._assert_curve_is(
                curve, zip(job_db.oq_params.imls, hc_db.poes), 0.005)

        self.teardown_job(job_db)

    def _assert_curve_is(self, expected, actual, tolerance):
        self.assertTrue(numpy.allclose(
                numpy.array(expected), numpy.array(actual), atol=tolerance),
                "Expected %s within a tolerance of %s, but was %s"
                % (expected, tolerance, actual))

    def _run_job(self, config_file):
        job = helpers.job_from_file(config_file)
        job.launch()

        return job

    def _load_results(self, test_name):
        """Return the hazard curves read from the expected_results/ dir.

        :returns: the expected hazard curves.
        :rtype: :py:class:`dict` where each key is an instance of
            :py:class:`openquake.shapes.Site` and each value is a list
            of (IML, PoE) tuples
        """

        # split the x string and get
        # the value at index y casted to float
        get = lambda x, y: float(x.split(",")[y])

        results_dir = helpers.smoketest_file(
            os.path.join(test_name, "expected_results"))

        results_files = os.listdir(results_dir)

        results = {}

        for result_file in results_files:
            path = os.path.join(results_dir, result_file)

            with open(path, "rb") as hazard_curve:
                lines = hazard_curve.readlines()
                coords = lines.pop(0)

                # the format is latitude,longitude
                site = shapes.Site(get(coords, 1), get(coords, 0))

                results[site] = []

                for pair in lines:
                    # the format is IML,PoE
                    results[site].append((get(pair, 0), get(pair, 1)))

        return results

@@ -886,16 +886,34 @@
 rt numpy
+%0Aimport subprocess
 %0A%0Afrom n
@@ -1269,38 +1269,32 @@
 Case2%22)%0A%0A       
- job =
  self._run_job(h
@@ -1385,39 +1385,38 @@
 %0A%0A        self._
-compare
+assert
 _results_for(job
@@ -1404,33 +1404,28 @@
 ert_results_
-for(job, 
+are(
 expected_res
@@ -1575,22 +1575,16 @@
 %0A       
- job =
  self._r
@@ -1691,23 +1691,22 @@
   self._
-compare
+assert
 _results
@@ -1710,17 +1710,12 @@
 lts_
-for(job, 
+are(
 expe
@@ -1742,15 +1742,14 @@
 ef _
-compare
+assert
 _res
@@ -1757,22 +1757,17 @@
 lts_
-for
+are
 (self,
- job,
  exp
@@ -1920,25 +1920,19 @@
 cts.
-get(id=job.job_
+latest(%22
 id
+%22
 )%0A%0A 
@@ -2795,36 +2795,80 @@
     
-job = helpers.job_from_file(
+sp = subprocess.Popen(%0A            %5B%22bin/openquake%22, %22--config_file=%22 + 
 conf
@@ -2874,17 +2874,19 @@
 fig_file
-)
+%5D)%0A
 %0A       
@@ -2890,40 +2890,17 @@
     
-job.launch()%0A%0A        return job
+sp.wait()
 %0A%0A  

Ran the tests as a separate process