/**
 * ** header v3.0
 * This file is a part of the CaosDB Project.
 *
 * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
 * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 *
 * ** end header
 */

USE _caosdb_schema_unit_tests;

BEGIN;
CALL tap.no_plan();

-- #####################################################################
-- TEST insertEntityProperty without Versioning
-- #####################################################################

-- SETUP
DELETE FROM entity_version;
DELETE FROM transactions;
INSERT INTO transactions (srid,seconds,nanos,username,realm) VALUES
("SRIDbla", 1234, 2345, "me", "home"),
("SRIDblub", 2345, 3465, "me", "home"),
("SRIDblieb", 3456, 4576, "you", "home");
SET @EntityID="99";
SET @PropertyID=11;
SET @Value=50;
SET @SRID="SRIDbla";
call insertEntity(@EntityID, "TheName", "TheDesc", "RecordType", "{}");
call insertEntity(@Value, "RefValue", "ValueDesc", "Record", "{}");
SELECT internal_id INTO @InternalEntityID FROM entity_ids WHERE id = @EntityID;
SELECT internal_id INTO @InternalValueID FROM entity_ids WHERE id = @Value;

-- switch off versioning
DELETE FROM feature_config WHERE _key = "ENTITY_VERSIONING";

-- TEST insertEntityProperty without Versioning
CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
    NULL, "FIX", NULL, NULL, NULL, NULL, 0);

-- TODO switch expected/actual
SELECT tap.eq("0", domain_id, "domain ok") FROM reference_data;
SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
SELECT tap.eq("11", property_id, "property ok") FROM reference_data;
SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
SELECT tap.eq(NULL, value_iversion, "value_iversion ok 1") FROM reference_data;

-- clean up
DELETE FROM reference_data WHERE domain_id=0 AND entity_id=@InternalValueID;

-- #####################################################################
-- TODO TEST insertEntityProperty with Versioning
-- #####################################################################

-- switch on versioning
INSERT INTO feature_config (_key, _value) VALUES ("ENTITY_VERSIONING", "ENABLED");


-- TEST insertEntityProperty with Versioning - REFERENCE HEAD
CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
    NULL, "FIX", NULL, NULL, NULL, NULL, 0);

-- TODO switch expected/actual
SELECT tap.eq(0, domain_id, "domain ok") FROM reference_data;
SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
SELECT tap.eq(11, property_id, "property ok") FROM reference_data;
SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
SELECT tap.eq(value_iversion, NULL, "value_iversion ok 2") FROM reference_data;

DELETE FROM reference_data WHERE domain_id=0 AND entity_id=@InternalEntityID;


-- TEST insertEntityProperty with Versioning - Reference version
SELECT * FROM entity_ids;
SELECT * FROM entity_version;
SELECT e.version INTO @ParentVersion
    FROM entity_version as e
    WHERE e.entity_id = @InternalValueID
    AND e._iversion = 1;
CALL insert_single_child_version(@InternalValueID, "hashblub", "versionblub", @ParentVersion, "SRIDblub");

SET @VALUE=CONCAT("50@", @ParentVersion);
CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
    NULL, "FIX", NULL, NULL, NULL, NULL, 0);

SELECT tap.eq(0, domain_id, "domain ok") FROM reference_data;
SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
SELECT tap.eq(11, property_id, "property ok") FROM reference_data;
SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
SELECT tap.eq(value_iversion, "1", "value_iversion ok 3") FROM reference_data;

DELETE FROM reference_data WHERE domain_id=0 AND entity_id=@InternalEntityID;

SET @VALUE="50@versionblub";
CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
    NULL, "FIX", NULL, NULL, NULL, NULL, 0);

-- TODO switch expected/actual
SELECT tap.eq(0, domain_id, "domain ok") FROM reference_data;
SELECT tap.eq(@InternalEntityID, entity_id, "entity ok") FROM reference_data;
SELECT tap.eq(11, property_id, "property ok") FROM reference_data;
SELECT tap.eq(@InternalValueID, value, "value ok") FROM reference_data;
SELECT tap.eq("FIX", status, "status ok") FROM reference_data;
SELECT tap.eq("0", pidx, "pidx ok") FROM reference_data;
SELECT tap.eq(value_iversion, "2", "value_iversion ok 4") FROM reference_data;


-- invalid values throw errors
SET @VALUE="50@";
CALL tap._assert_throws('
    CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
        NULL, "FIX", NULL, NULL, NULL, NULL, 0)', "@ but no version id");

SET @VALUE="50@non-existing-version";
CALL tap._assert_throws('
    CALL insertEntityProperty(0, @EntityID, @PropertyID, "reference_data", @Value,
        NULL, "FIX", NULL, NULL, NULL, NULL, 0)', "non-existing-version id");


-- #####################################################################
-- TEST retrieveEntityProperty without Versioning
-- #####################################################################

CALL tap.finish();
ROLLBACK;