#!/usr/bin/env python
###############################################################################
# $Id$
#
#  Project:  PROJ
#  Purpose:  Populate data/sql/nadcon5_concatenated_operations.sql
#  Author:   Even Rouault <even.rouault at spatialys.com>
#
###############################################################################
#  Copyright (c) 2022, Even Rouault <even.rouault at spatialys.com>
#
#  Permission is hereby granted, free of charge, to any person obtaining a
#  copy of this software and associated documentation files (the "Software"),
#  to deal in the Software without restriction, including without limitation
#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
#  and/or sell copies of the Software, and to permit persons to whom the
#  Software is furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included
#  in all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#  DEALINGS IN THE SOFTWARE.
###############################################################################

import os

script_dir_name = os.path.dirname(os.path.realpath(__file__))
sql_dir_name = os.path.join(os.path.dirname(script_dir_name), 'data', 'sql')

out_filename = os.path.join(sql_dir_name, 'nadcon5_concatenated_operations') + '.sql'
#print(out_filename)

def sanitize_crs_name_for_code(name):
    return name.replace('(', '_').replace(')', '').replace(' ','_').upper()

def gen_transformations(sql, transformations, crs_dict, short_area_of_use, extent_code):
    for i in range(len(transformations)):
        for j in range(i,len(transformations)):
            if i >= j:
                continue
            source_crs = transformations[i][0]
            target_crs = transformations[j][1]

            total_acc = 0
            for k in range(i,j+1):
                total_acc += transformations[k][3] ** 2
            total_acc = total_acc ** 0.5
            total_acc = round(total_acc * 100) / 100.0

            transfm_code = sanitize_crs_name_for_code(source_crs) + "_TO_" + sanitize_crs_name_for_code(target_crs) + "_" + short_area_of_use.upper()
            transfm_name = f"{source_crs} to {target_crs} (NADCON5, {short_area_of_use})"

            source_crs_code = crs_dict[source_crs][0]
            target_crs_code = crs_dict[target_crs][0]

            sql += f"INSERT INTO concatenated_operation VALUES('PROJ','{transfm_code}','{transfm_name}','Transformation based on concatenation of NADCON5 transformations','EPSG','{source_crs_code}','EPSG','{target_crs_code}',{total_acc},NULL,0);\n"

            for k in range(i,j+1):
                step = k - i + 1
                source_crs_name = transformations[k][0]
                target_crs_name = transformations[k][1]
                step_code = transformations[k][2]
                acc = transformations[k][3]
                sql += f"INSERT INTO concatenated_operation_step VALUES('PROJ','{transfm_code}',{step},'EPSG','{step_code}','forward'); -- {source_crs_name} to {target_crs_name} (EPSG:{step_code}), {acc} m\n"

            sql += f"INSERT INTO usage VALUES('PROJ','{transfm_code}_USAGE','concatenated_operation','PROJ','{transfm_code}',\n"
            sql += f"    'EPSG','{extent_code}', -- extent: {short_area_of_use}\n"
            sql += f"    'EPSG','1027' -- scope: Geodesy\n"
            sql += ");\n"

            sql += "\n"

    return sql

crs_dict = {
    "NAD27" : (4267, 0),
    "Puerto Rico": (4139, 0),
    "Old Hawaiian": (4135, 0),
    "American Samoa 1962": (4169, 0),
    "Guam 1963": (4675, 0),
    "NAD83" : (4269, 0),
    "NAD83(HARN)": (4152, 4957),
    "NAD83(HARN Corrected)": (8545, 8544), # PRVI only
    "NAD83(FBN)": (8860, 8542),
    "NAD83(NSRS2007)": (4759, 4893),
    "NAD83(2011)": (6318, 6319),
    "NAD83(PA11)": (6322, 6321),
    "NAD83(MA11)": (6325, 6324),
}

f = open(out_filename, 'wb')
f.write("--- This file has been generated by scripts/build_nadcon5_concatenated_operations.py. DO NOT EDIT !\n\n".encode('UTF-8'))

f.write("-- Concatenated accuracy is sqrt(sum of squared accuracies) (confirmed by NGS to be a valid way)\n\n".encode('UTF-8'))

sql = ""

# CONUS
transformations = [
    ("NAD27", "NAD83", 8555, 0.15),
    ("NAD83", "NAD83(HARN)", 8556, 0.05),
    ("NAD83(HARN)", "NAD83(FBN)", 8861, 0.05),
    ("NAD83(FBN)", "NAD83(NSRS2007)", 8862, 0.05),
    ("NAD83(NSRS2007)", "NAD83(2011)", 8559, 0.05),
]

sql = gen_transformations(sql, transformations, crs_dict, "CONUS", 4516)

# Alaska
transformations = [
    ("NAD27", "NAD83", 8549, 0.5),
    ("NAD83", "NAD83(HARN)", 8550, 0.15),
    ("NAD83(HARN)", "NAD83(NSRS2007)", 8551, 0.05),
    ("NAD83(NSRS2007)", "NAD83(2011)", 8552, 0.05),
]

sql = gen_transformations(sql, transformations, crs_dict, "Alaska", 1330)

# Hawaii
transformations = [
    ("Old Hawaiian", "NAD83", 8561, 0.2),
    ("NAD83", "NAD83(HARN)", 8660, 0.05),
    ("NAD83(HARN)", "NAD83(PA11)", 8661, 0.05),
]

sql = gen_transformations(sql, transformations, crs_dict, "Hawaii", 1334)

# PRVI
transformations = [
    ("Puerto Rico", "NAD83", 8668, 0.15),
    ("NAD83", "NAD83(HARN)", 8669, 0.15),
    ("NAD83(HARN)", "NAD83(HARN Corrected)", 9181, 0.05),
    ("NAD83(HARN Corrected)", "NAD83(FBN)", 8867, 0.05),
    ("NAD83(FBN)", "NAD83(NSRS2007)", 8868, 0.05),
    ("NAD83(NSRS2007)", "NAD83(2011)", 8673, 0.05),
]

sql = gen_transformations(sql, transformations, crs_dict, "PRVI", 3634)

# American Samoa
transformations = [
    ("American Samoa 1962", "NAD83(HARN)", 8662, 5.0),
    ("NAD83(HARN)", "NAD83(FBN)", 8863, 0.05),
    ("NAD83(FBN)", "NAD83(PA11)", 8864, 0.05),
]

sql = gen_transformations(sql, transformations, crs_dict, "AS", 3110)

# Guam
transformations = [
    ("Guam 1963", "NAD83(HARN)", 8665, 5.0),
    ("NAD83(HARN)", "NAD83(FBN)", 8865, 0.05),
    ("NAD83(FBN)", "NAD83(MA11)", 8866, 0.05),
]

sql = gen_transformations(sql, transformations, crs_dict, "GUAM", 4525)

f.write(sql.encode('UTF-8'))

f.close()
