import os

import numpy as np
import pytest
import easyidp
from easyidp.core.objects import ReconsProject, Points
from easyidp.io import metashape

module_path = os.path.join(easyidp.__path__[0], "io/tests")


def test_init_reconsproject():
    attempt1 = ReconsProject("agisoft")
    assert attempt1.software == "metashape"

    attempt2 = ReconsProject("Metashape")
    assert attempt2.software == "metashape"

    with pytest.raises(LookupError):
        attempt3 = ReconsProject("not_supported_sfm")


def test_local2world2local():
    attempt1 = ReconsProject("agisoft")
    attempt1.transform.matrix = np.asarray([[-0.86573098, -0.01489186, 0.08977677, 7.65034123],
                                            [0.06972335, 0.44334391, 0.74589315, 1.85910928],
                                            [-0.05848325, 0.74899678, -0.43972184, -0.1835615],
                                            [0., 0., 0., 1.]], dtype=np.float)
    w_pos = Points([0.5, 1, 1.5])
    l_pos = Points([7.960064093299587, 1.3019528769064523, -2.6697181763370965])
    w_pos_ans = Points([0.4999999999999978, 0.9999999999999993, 1.5])

    world_pos = attempt1.local2world(l_pos)
    np.testing.assert_array_almost_equal(w_pos_ans.values, world_pos.values, decimal=6)

    local_pos = attempt1.world2local(w_pos)
    np.testing.assert_array_almost_equal(l_pos.values, local_pos.values, decimal=6)


def test_metashape_project_local_points_on_raw():
    test_project_folder = easyidp.test_full_path("data/metashape/goya_test.psx")
    chunks = metashape.open_project(test_project_folder)

    chunk = chunks[0]

    # test for single point
    l_pos = Points([7.960064093299587, 1.3019528769064523, -2.6697181763370965])

    p_dis_out = chunk.project_local_points_on_raw(l_pos, 0, distortion_correct=False)
    p_undis_out = chunk.project_local_points_on_raw(l_pos, 0, distortion_correct=True)

    # pro_api_out = np.asarray([2218.883386793118, 1991.4709388015149])
    my_undistort_out = Points([2220.854889556147, 1992.6933680261686])
    my_distort_out = Points([2218.47960556, 1992.46356322])

    np.testing.assert_array_almost_equal(p_dis_out.values, my_distort_out.values)
    np.testing.assert_array_almost_equal(p_undis_out.values, my_undistort_out.values)

    # test for multiple points
    l_pos_points = Points([[7.960064093299587, 1.3019528769064523, -2.6697181763370965],
                           [7.960064093299587, 1.3019528769064523, -2.6697181763370965]])

    p_dis_outs = chunk.project_local_points_on_raw(l_pos_points, 0, distortion_correct=False)
    p_undis_outs = chunk.project_local_points_on_raw(l_pos_points, 0, distortion_correct=True)

    my_undistort_outs = Points([[2220.854889556147, 1992.6933680261686],
                                [2220.854889556147, 1992.6933680261686]])
    my_distort_outs = Points([[2218.47960556, 1992.46356322],
                              [2218.47960556, 1992.46356322]])

    np.testing.assert_array_almost_equal(p_dis_outs.values, my_distort_outs.values)
    np.testing.assert_array_almost_equal(p_undis_outs.values, my_undistort_outs.values)


def test_world2crs_and_on_raw_images():
    test_project_folder = easyidp.test_full_path("data/metashape/wheat_tanashi.psx")
    chunks = metashape.open_project(test_project_folder)

    chunk = chunks[0]

    local = Points([11.870130675203006, 0.858098777517136, -12.987136541275])
    geocentric = Points([-3943658.7087006606, 3363404.124223561, 3704651.3067566575])
    geodetic = Points([139.54033578028609, 35.73756358928734, 96.87827569602781], columns=['lon', 'lat', 'alt'])

    idp_world = chunk.local2world(local)
    np.testing.assert_array_almost_equal(idp_world.values, geocentric.values, decimal=1)

    idp_crs = chunk.world2crs(idp_world)
    np.testing.assert_array_almost_equal(idp_crs.values, geodetic.values)

    camera_id = 56   # camera_label = 'DJI_0057'
    camera_pix_ans = Points([2391.7104647010146, 1481.8987733175165])

    idp_cam_pix = chunk.project_local_points_on_raw(local, camera_id, distortion_correct=True)
    np.testing.assert_array_almost_equal(camera_pix_ans.values, idp_cam_pix.values)



[((9, 14, 9, 59), 'os.path.join', 'os.path.join', ({(9, 27, 9, 46): 'easyidp.__path__[0]', (9, 48, 9, 58): '"""io/tests"""'}, {}), "(easyidp.__path__[0], 'io/tests')", False, 'import os\n'), ((13, 15, 13, 39), 'easyidp.core.objects.ReconsProject', 'ReconsProject', ({(13, 29, 13, 38): '"""agisoft"""'}, {}), "('agisoft')", False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((16, 15, 16, 41), 'easyidp.core.objects.ReconsProject', 'ReconsProject', ({(16, 29, 16, 40): '"""Metashape"""'}, {}), "('Metashape')", False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((24, 15, 24, 39), 'easyidp.core.objects.ReconsProject', 'ReconsProject', ({(24, 29, 24, 38): '"""agisoft"""'}, {}), "('agisoft')", False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((25, 32, 28, 78), 'numpy.asarray', 'np.asarray', (), '', True, 'import numpy as np\n'), ((29, 12, 29, 33), 'easyidp.core.objects.Points', 'Points', ({(29, 19, 29, 32): '[0.5, 1, 1.5]'}, {}), '([0.5, 1, 1.5])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((30, 12, 30, 80), 'easyidp.core.objects.Points', 'Points', ({(30, 19, 30, 79): '[7.960064093299587, 1.3019528769064523, -2.6697181763370965]'}, {}), '([7.960064093299587, 1.3019528769064523, -2.6697181763370965])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((31, 16, 31, 69), 'easyidp.core.objects.Points', 'Points', ({(31, 23, 31, 68): '[0.4999999999999978, 0.9999999999999993, 1.5]'}, {}), '([0.4999999999999978, 0.9999999999999993, 1.5])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((34, 4, 34, 87), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', (), '', True, 'import numpy as np\n'), ((37, 4, 37, 83), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', (), '', True, 'import numpy as np\n'), ((41, 26, 41, 80), 'easyidp.test_full_path', 'easyidp.test_full_path', ({(41, 49, 41, 79): '"""data/metashape/goya_test.psx"""'}, {}), "('data/metashape/goya_test.psx')", False, 'import easyidp\n'), ((42, 13, 42, 56), 'easyidp.io.metashape.open_project', 'metashape.open_project', ({(42, 36, 42, 55): 'test_project_folder'}, {}), '(test_project_folder)', False, 'from easyidp.io import metashape\n'), ((47, 12, 47, 80), 'easyidp.core.objects.Points', 'Points', ({(47, 19, 47, 79): '[7.960064093299587, 1.3019528769064523, -2.6697181763370965]'}, {}), '([7.960064093299587, 1.3019528769064523, -2.6697181763370965])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((53, 23, 53, 70), 'easyidp.core.objects.Points', 'Points', ({(53, 30, 53, 69): '[2220.854889556147, 1992.6933680261686]'}, {}), '([2220.854889556147, 1992.6933680261686])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((54, 21, 54, 59), 'easyidp.core.objects.Points', 'Points', ({(54, 28, 54, 58): '[2218.47960556, 1992.46356322]'}, {}), '([2218.47960556, 1992.46356322])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((56, 4, 56, 81), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', ({(56, 41, 56, 57): 'p_dis_out.values', (56, 59, 56, 80): 'my_distort_out.values'}, {}), '(p_dis_out.values, my_distort_out.values)', True, 'import numpy as np\n'), ((57, 4, 57, 85), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', ({(57, 41, 57, 59): 'p_undis_out.values', (57, 61, 57, 84): 'my_undistort_out.values'}, {}), '(p_undis_out.values, my_undistort_out.\n    values)', True, 'import numpy as np\n'), ((60, 19, 61, 89), 'easyidp.core.objects.Points', 'Points', ({(60, 26, 61, 88): '[[7.960064093299587, 1.3019528769064523, -2.6697181763370965], [\n    7.960064093299587, 1.3019528769064523, -2.6697181763370965]]'}, {}), '([[7.960064093299587, 1.3019528769064523, -2.6697181763370965], [\n    7.960064093299587, 1.3019528769064523, -2.6697181763370965]])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((66, 24, 67, 73), 'easyidp.core.objects.Points', 'Points', ({(66, 31, 67, 72): '[[2220.854889556147, 1992.6933680261686], [2220.854889556147, \n    1992.6933680261686]]'}, {}), '([[2220.854889556147, 1992.6933680261686], [2220.854889556147, \n    1992.6933680261686]])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((68, 22, 69, 62), 'easyidp.core.objects.Points', 'Points', ({(68, 29, 69, 61): '[[2218.47960556, 1992.46356322], [2218.47960556, 1992.46356322]]'}, {}), '([[2218.47960556, 1992.46356322], [2218.47960556, 1992.46356322]])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((71, 4, 71, 83), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', ({(71, 41, 71, 58): 'p_dis_outs.values', (71, 60, 71, 82): 'my_distort_outs.values'}, {}), '(p_dis_outs.values, my_distort_outs.values)', True, 'import numpy as np\n'), ((72, 4, 72, 87), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', ({(72, 41, 72, 60): 'p_undis_outs.values', (72, 62, 72, 86): 'my_undistort_outs.values'}, {}), '(p_undis_outs.values, my_undistort_outs\n    .values)', True, 'import numpy as np\n'), ((76, 26, 76, 84), 'easyidp.test_full_path', 'easyidp.test_full_path', ({(76, 49, 76, 83): '"""data/metashape/wheat_tanashi.psx"""'}, {}), "('data/metashape/wheat_tanashi.psx')", False, 'import easyidp\n'), ((77, 13, 77, 56), 'easyidp.io.metashape.open_project', 'metashape.open_project', ({(77, 36, 77, 55): 'test_project_folder'}, {}), '(test_project_folder)', False, 'from easyidp.io import metashape\n'), ((81, 12, 81, 77), 'easyidp.core.objects.Points', 'Points', ({(81, 19, 81, 76): '[11.870130675203006, 0.858098777517136, -12.987136541275]'}, {}), '([11.870130675203006, 0.858098777517136, -12.987136541275])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((82, 17, 82, 85), 'easyidp.core.objects.Points', 'Points', ({(82, 24, 82, 84): '[-3943658.7087006606, 3363404.124223561, 3704651.3067566575]'}, {}), '([-3943658.7087006606, 3363404.124223561, 3704651.3067566575])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((83, 15, 83, 112), 'easyidp.core.objects.Points', 'Points', (), '', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((86, 4, 86, 88), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', (), '', True, 'import numpy as np\n'), ((89, 4, 89, 73), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', ({(89, 41, 89, 55): 'idp_crs.values', (89, 57, 89, 72): 'geodetic.values'}, {}), '(idp_crs.values, geodetic.values)', True, 'import numpy as np\n'), ((92, 21, 92, 69), 'easyidp.core.objects.Points', 'Points', ({(92, 28, 92, 68): '[2391.7104647010146, 1481.8987733175165]'}, {}), '([2391.7104647010146, 1481.8987733175165])', False, 'from easyidp.core.objects import ReconsProject, Points\n'), ((95, 4, 95, 83), 'numpy.testing.assert_array_almost_equal', 'np.testing.assert_array_almost_equal', ({(95, 41, 95, 62): 'camera_pix_ans.values', (95, 64, 95, 82): 'idp_cam_pix.values'}, {}), '(camera_pix_ans.values, idp_cam_pix.values)', True, 'import numpy as np\n'), ((19, 9, 19, 35), 'pytest.raises', 'pytest.raises', ({(19, 23, 19, 34): 'LookupError'}, {}), '(LookupError)', False, 'import pytest\n'), ((20, 19, 20, 53), 'easyidp.core.objects.ReconsProject', 'ReconsProject', ({(20, 33, 20, 52): '"""not_supported_sfm"""'}, {}), "('not_supported_sfm')", False, 'from easyidp.core.objects import ReconsProject, Points\n')]