import csv
import numpy as np
import cv2
from imageio import imread

lines = []
with open('data/driving_log.csv') as csvfile:
    reader = csv.reader(csvfile)
    for line in reader:
        lines.append(line)

print("Preparing Dataset...")
images = []
measurements = []
for line in lines:
    for i in range(0,3):
        source_path = line[i]
        filename = source_path.split('\\')[-1]
        current_path = 'data/IMG/' + filename
        image = imread(current_path)
        images.append(image)
        measurement = float(line[3])
        if i==0 :
            measurements.append(measurement)
        elif i==1 :
            measurements.append(measurement+0.25)
        elif i==2 :
            measurements.append(measurement-0.25)
        measurements.append(measurement)

augmented_images, augmented_measurements = [], []
for image, measurement in zip(images,measurements):
    augmented_images.append(image)
    augmented_measurements.append(measurement)
    augmented_images.append(cv2.flip(image,1))
    augmented_measurements.append(measurement*-1.0)

X_train = np.array(augmented_images)
y_train = np.array(augmented_measurements)

print("Dataset Prepared!!")
# from keras.models import Sequential
# from keras.layers import Flatten, Dense, Lambda, Dropout
# from keras.layers import MaxPooling2D, Conv2D

# model = Sequential()
# # Normalize image
# model.add(Lambda(lambda x: (x / 255.0) - 0.5, input_shape=(160,320,3)))
# # Convolution 5x5 Layers
# model.add(Conv2D(24,5,5,subsample=(2,2),activation='relu'))
# model.add(Conv2D(36,5,5,subsample=(2,2),activation='relu'))
# model.add(Conv2D(48,5,5,subsample=(2,2),activation='relu'))
# # Convolution 3x3 Layers
# model.add(Conv2D(64,3,3,activation='relu'))
# model.add(Conv2D(64,3,3,activation='relu'))
# model.add(MaxPooling2D(pool_size=(2,2), dim_ordering="th"))
# model.add(Dropout(0.5))
# model.add(Flatten())
# # Full-Connected Layers
# model.add(Dense(100))
# model.add(Dense(50))
# model.add(Dense(10))
# model.add(Dense(1))


# model.compile(loss='mse', optimizer='adam')
# model.fit(X_train, y_train, validation_split=0.2, shuffle=True, nb_epoch=5)

# model.save('model.h5')

from keras.models import Sequential
from keras.layers.core import Dense, Flatten, Activation, Dropout
from keras.layers.convolutional import Convolution2D
from keras.layers import Lambda, Cropping2D

model = Sequential()

# Preprocess incoming data, centered around zero with small standard deviation 
model.add(Lambda(lambda x: (x / 255.0) - 0.5, input_shape=(160,320,3)))

# # trim image to only see section with road
# model.add(Cropping2D(cropping=((70,25),(0,0))))           

#layer 1- Convolution, no of filters- 24, filter size= 5x5, stride= 2x2
model.add(Convolution2D(24,5,5,subsample=(2,2)))
model.add(Activation('elu'))

#layer 2- Convolution, no of filters- 36, filter size= 5x5, stride= 2x2
model.add(Convolution2D(36,5,5,subsample=(2,2)))
model.add(Activation('elu'))

#layer 3- Convolution, no of filters- 48, filter size= 5x5, stride= 2x2
model.add(Convolution2D(48,5,5,subsample=(2,2)))
model.add(Activation('elu'))

#layer 4- Convolution, no of filters- 64, filter size= 3x3, stride= 1x1
model.add(Convolution2D(64,3,3))
model.add(Activation('elu'))

#layer 5- Convolution, no of filters- 64, filter size= 3x3, stride= 1x1
model.add(Convolution2D(64,3,3))
model.add(Activation('elu'))

#flatten image from 2D to side by side
model.add(Flatten())

#layer 6- fully connected layer 1
model.add(Dense(100))
model.add(Activation('elu'))

#Adding a dropout layer to avoid overfitting. Here we are have given the dropout rate as 25% after first fully connected layer
model.add(Dropout(0.25))

#layer 7- fully connected layer 1
model.add(Dense(50))
model.add(Activation('elu'))


#layer 8- fully connected layer 1
model.add(Dense(10))
model.add(Activation('elu'))

#layer 9- fully connected layer 1
model.add(Dense(1)) #here the final layer will contain one value as this is a regression problem and not classification


# the output is the steering angle
# using mean squared error loss function is the right choice for this regression problem
# adam optimizer is used here
model.compile(loss='mse',optimizer='adam')


#fit generator is used here as the number of images are generated by the generator
# no of epochs : 5

model.fit(X_train, y_train, validation_split=0.2, shuffle=True, nb_epoch=5)
#saving model
model.save('model.h5')

print('Done! Model Saved!')

# keras method to print the model summary
model.summary()