import os
import shutil
import unittest
import numpy as np

from pytest import raises


def read(path):
    if not os.path.exists(path):
        raise FileNotFoundError('File not found: {}'.format(path))

    with open(path, 'r') as ply:
        try:
            first_line = ply.readline()
        except UnicodeDecodeError:
            first_line = ''

        if 'ply' not in first_line:
            raise ValueError('Not a valid ply file: {}'.format(path))

        for line in ply:
            index = []
            element_type = 'vertex'
            element_vertex_ = 'element {} '.format(element_type)
            if element_vertex_ in line:
                number_of_elements = int(line.split(element_vertex_)[1])
                index.append({'type': element_type, 'number_of_elements': number_of_elements})

            return [[None for i in range(element_block['number_of_elements'])] for element_block in index]


class TestReadPly(unittest.TestCase):
    _test_dir = 'TestLoad_dir'
    _test_file_name = 'example.ply'
    _las_file_name = '5points.las'
    _test_data_source = 'testdata'
    las_file_path = os.path.join(_test_dir, _las_file_name)
    test_file_path = os.path.join(_test_dir, _test_file_name)

    def test_unexistentFile_error(self):
        with raises(OSError):
            read('nonexistentfile.ply')

    def test_wrongFormat_error(self):
        with raises(ValueError):
            read(self.las_file_path)

    def test_existentPly_noError(self):
        read(self.test_file_path)

    def test_containsPointsElement(self):
        data = read(self.test_file_path)
        self.assertIn('points', data)

    def test_rightNumberOfPoints(self):
        data = read(self.test_file_path)
        self.assertEqual(len(data['points']), 3)

    def test_correctPoints(self):
        data = read(self.test_file_path)
        np.testing.assert_allclose(data['points'][0]['data'], np.array([0.11, 0.12, 0.13, 1]))

    def setUp(self):
        os.mkdir(self._test_dir)
        shutil.copyfile(os.path.join(self._test_data_source, self._test_file_name), self.test_file_path)
        shutil.copyfile(os.path.join(self._test_data_source, self._las_file_name), self.las_file_path)

    def tearDown(self):
        shutil.rmtree(self._test_dir)

@@ -80,16 +80,47 @@
 raises%0A%0A
+from laserchicken import keys%0A%0A
 %0Adef rea
@@ -482,24 +482,43 @@
 mat(path))%0A%0A
+        index = %5B%5D%0A
         for 
@@ -534,31 +534,8 @@
 ly:%0A
-            index = %5B%5D%0A
     
@@ -764,194 +764,1103 @@
     
-index.append(%7B'type': element_type, 'number_of_elements': number_of_elements%7D)%0A%0A            return %5B%5BNone for i in range(element_block%5B'number_of_elements'%5D)%5D for element_block in index%5D
+current_properties = %5B%5D%0A                index.append(%0A                    %7B'type': element_type, 'number_of_elements': number_of_elements, 'properties': current_properties%7D)%0A%0A            if line%5B:9%5D == 'property ':%0A                property_type, property_name = line%5B9:%5D.strip('%5Cn').split(' ')%0A                current_properties.append(%7B'type': property_type, 'name': property_name%7D)%0A%0A        return %7Bblock%5B'type'%5D: read_block(block, ply) for block in index%7D%0A%0A%0Adef read_block(block, ply_body):%0A    properties = %7B%7D%0A    for prop in block%5B'properties'%5D:%0A        if prop%5B'type'%5D == 'float':%0A            dtype = np.float64%0A        if prop%5B'type'%5D == 'int':%0A            dtype = np.int32%0A        properties%5Bprop%5B'name'%5D%5D = %7B'type': prop%5B'type'%5D, 'data': np.zeros(block%5B'number_of_elements'%5D, dtype)%7D%0A    for i in range(block%5B'number_of_elements'%5D):%0A        pass%0A        # line = ply_body.readline()%0A        # values = line.split(' ')%0A        # if len(values) != len(block%5B'properties'%5D):%0A        #     raise ValueError('Error reading line %7B%7D of %7B%7D list.'.format(i, block%5B'type'%5D))%0A    return properties
 %0A%0A%0Ac
@@ -2561,22 +2561,148 @@
 tIn(
-'points', data
+keys.point, data)%0A%0A    def test_containsXElement(self):%0A        data = read(self.test_file_path)%0A        self.assertIn('x', data%5Bkeys.point%5D
 )%0A%0A 
@@ -2815,23 +2815,38 @@
 en(data%5B
-'points
+keys.point%5D%5B'x'%5D%5B'data
 '%5D), 3)%0A
@@ -2933,60 +2933,173 @@
     
-np.testing.assert_allclose(data%5B'points'%5D%5B0%5D%5B'data'%5D
+points = data%5Bkeys.point%5D%0A        point = np.array(%5Bpoints%5B'x'%5D%5B'data'%5D%5B0%5D, points%5B'y'%5D%5B'data'%5D%5B0%5D, points%5B'z'%5D%5B'data'%5D%5B0%5D%5D)%0A        np.testing.assert_allclose(point
 , np

add read properties of ply file