function varargout = build_road_gui(varargin)

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @build_road_gui_OpeningFcn, ...
                   'gui_OutputFcn',  @build_road_gui_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before build_road_gui is made visible.
function build_road_gui_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to build_road_gui (see VARARGIN)

% Choose default command line output for build_road_gui
handles.output = hObject;

handles.ax = gca;%findobj(hObject, 'tag', 'gui_figure');
handles.gui_helper = ScenarioGUIHelper.empty(0);

handles.kCROSSWALK_VERT = 1;
handles.kCROSSWALK_HORZ = 2;
handles.kUP = 1;
handles.kRIGHT = 2;
handles.kDOWN = 3;
handles.kLEFT = 4;
handles.crosswalk_dir = handles.kCROSSWALK_HORZ;
handles.stopsign_dir = handles.kUP;
handles.crosswalk_ped_freq = 0;
handles.crosswalk_ped_duty = 0;

guidata(hObject, handles);

function varargout = build_road_gui_OutputFcn(hObject, eventdata, handles) 
varargout{1} = handles.output;

function road_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    insertRoad(handles);
end

function left_button_road_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([-1, 0])
    insertRoad(handles);
end

function right_button_road_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([1, 0])
    insertRoad(handles);
end

function up_button_road_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([0, 1])
    insertRoad(handles);
end

function down_button_road_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([0, -1])
    insertRoad(handles);
end

function intersection_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    
end

function gui_figure_ButtonDownFcn(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    
end

function goal_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    if(roadCellExist(handles, handles.gui_helper.cursor_cell))
        [goal_already_exists, at_line] = cellTypeExist(handles, 'goal');
        if goal_already_exists
            deleteLine(handles, at_line)
        end
        startNewLine(handles); % make sure start at new line.
        fid = fopen(handles.gui_helper.scenario_file, 'a');
        
%         handles.gui_helper.setStartStateVals(handles.start_state_gui_vals);
        fprintf(fid, '%d,%d,goal\n', handles.gui_helper.cursor_cell);
        fclose(fid);
        handles.gui_helper.refresh();
    end
end


function start_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    if(roadCellExist(handles, handles.gui_helper.cursor_cell))
        [start_already_exists, at_line] = cellTypeExist(handles, 'start');
        if start_already_exists
            deleteLine(handles, at_line)
        end
        startNewLine(handles); % make sure start at new line.
        fid = fopen(handles.gui_helper.scenario_file, 'a');
        
        handles.gui_helper.setStartStateVals(handles.start_state_gui_vals);
        fprintf(fid, '%d,%d,start,%.3f,%.3f,%.3f,%.3f\n', [handles.gui_helper.cursor_cell, handles.gui_helper.start_state]);
        fclose(fid);
        handles.gui_helper.refresh();
    end
        
end

function x_start_Callback(hObject, eventdata, handles)
handles.start_state_gui_vals(1) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function x_start_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

handles.start_state_gui_vals(1) = str2double(get(hObject,'String'));
guidata(hObject, handles);


function y_start_Callback(hObject, eventdata, handles)
handles.start_state_gui_vals(2) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function y_start_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
handles.start_state_gui_vals(2) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function theta_start_Callback(hObject, eventdata, handles)
handles.start_state_gui_vals(3) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function theta_start_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
handles.start_state_gui_vals(3) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function v_start_Callback(hObject, eventdata, handles)
handles.start_state_gui_vals(4) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function v_start_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
handles.start_state_gui_vals(4) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function up_cell_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([0, 1])
end

function right_cell_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([1, 0])
end

function left_cell_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([-1, 0])
end

function down_cell_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    handles.gui_helper.moveCursor([0, -1])
end

function undo_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    deleteLine(handles, -1);
    handles.gui_helper.refresh();
end

function filename_edit_Callback(hObject, eventdata, handles)
handles.scenario_file = get(hObject,'String');
guidata(hObject, handles);

function filename_edit_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
handles.scenario_file = get(hObject,'String');
guidata(hObject, handles);

function begin_button_Callback(hObject, eventdata, handles)
if ~exist(handles.scenario_file, 'file')
    newFile(handles.scenario_file);
end
handles.gui_helper = ScenarioGUIHelper(handles.ax, handles.scenario_file);

handles.gui_helper.scene.kCROSSWALK_VERT = handles.kCROSSWALK_VERT;
handles.gui_helper.scene.kCROSSWALK_HORZ = handles.kCROSSWALK_HORZ;
handles.gui_helper.scene.kUP = handles.kUP;
handles.gui_helper.scene.kRIGHT = handles.kRIGHT;
handles.gui_helper.scene.kDOWN = handles.kDOWN;
handles.gui_helper.scene.kLEFT = handles.kLEFT;

guidata(hObject, handles);

function stopsign_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
   if(roadCellExist(handles, handles.gui_helper.cursor_cell))
        already_exists = cellTypeExist(handles, 'stopsign', handles.gui_helper.cursor_cell, handles.stopsign_dir);
        if already_exists
            return
        end
        startNewLine(handles); % make sure start at new line.
        fid = fopen(handles.gui_helper.scenario_file, 'a');
        
        fprintf(fid, '%d,%d,stopsign,%d\n', [handles.gui_helper.cursor_cell,handles.stopsign_dir]);
        fclose(fid);
        handles.gui_helper.refresh();
    end    
end

function up_button_stopsign_Callback(hObject, eventdata, handles)
handles.stopsign_dir = handles.gui_helper.scene.kUP;
guidata(hObject, handles);

function down_button_stopsign_Callback(hObject, eventdata, handles)
handles.stopsign_dir = handles.gui_helper.scene.kDOWN;
guidata(hObject, handles);

function left_button_stopsign_Callback(hObject, eventdata, handles)
handles.stopsign_dir = handles.gui_helper.scene.kLEFT;
guidata(hObject, handles);

function right_button_stopsign_Callback(hObject, eventdata, handles)
handles.stopsign_dir = handles.gui_helper.scene.kRIGHT;
guidata(hObject, handles);

function crosswalk_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
   if(roadCellExist(handles, handles.gui_helper.cursor_cell))
        [already_exists, at_line] = cellTypeExist(handles, 'crosswalk', handles.gui_helper.cursor_cell);
        if already_exists
            deleteLine(handles, at_line)
        end
        startNewLine(handles); % make sure start at new line.
        fid = fopen(handles.gui_helper.scenario_file, 'a');
        
        fprintf(fid, '%d,%d,crosswalk,%d,%.3f,%.3f\n', [handles.gui_helper.cursor_cell,handles.crosswalk_dir,handles.crosswalk_ped_freq,handles.crosswalk_ped_duty]);
        fclose(fid);
        handles.gui_helper.refresh();
    end    
end

function vertical_button_crosswalk_Callback(hObject, eventdata, handles)
handles.crosswalk_dir = handles.gui_helper.scene.kCROSSWALK_VERT;
guidata(hObject, handles);

function horizontal_button_crosswalk_Callback(hObject, eventdata, handles)
handles.crosswalk_dir = handles.gui_helper.scene.kCROSSWALK_HORZ;
guidata(hObject, handles);

function crosswalk_ped_freq_Callback(hObject, eventdata, handles)
handles.crosswalk_ped_freq = str2double(get(hObject,'String'));
guidata(hObject, handles);

function crosswalk_ped_freq_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

handles.crosswalk_ped_freq = str2double(get(hObject,'String'));
guidata(hObject, handles);

function crosswalk_ped_duty_Callback(hObject, eventdata, handles)
handles.crosswalk_ped_duty = str2double(get(hObject,'String'));
guidata(hObject, handles);


function crosswalk_ped_duty_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

handles.crosswalk_ped_duty = str2double(get(hObject,'String'));
guidata(hObject, handles);

% HELPER FUNCTIONS:
function startNewLine(handles)
% Adds '\n' to end of file if not already there.
fid = fopen(handles.gui_helper.scenario_file, 'r');
fseek(fid, -1, 'eof');
lastchar = fread(fid);
fclose(fid);
if lastchar ~= 10
    fid = fopen(handles.gui_helper.scenario_file, 'a');
    fprintf(fid, '\n');
    fclose(fid);
end

function insertRoad(handles)
% Adds a road cell at end of file.
% FIXME: Currently all roads have same name ROADNAME
if ~roadCellExist(handles, handles.gui_helper.cursor_cell)
    startNewLine(handles); % make sure start at new line.
    fid = fopen(handles.gui_helper.scenario_file, 'a');
    fprintf(fid, '%d,%d,road,ROADNAME\n', handles.gui_helper.cursor_cell);
    fclose(fid);
    handles.gui_helper.refresh();
end

function doesExist = roadCellExist(handles, cell)
% Checks if a road cell already exists in the file
fid = fopen(handles.gui_helper.scenario_file, 'r');
data = fread(fid, '*char')';
fclose(fid);
data = regexp(data, {'\n'}, 'split');
data_lines = regexp(data{1}, ',', 'split');
data_len = length(data{1});
for i=2:data_len
    if length(data_lines{i}) < 3
        continue;
    end
    if str2double(data_lines{i}{1}) == cell(1) ...
            && str2double(data_lines{i}{2}) == cell(2) ...
            && strcmp(data_lines{i}{3}, 'road')
 
        doesExist = true;
        return
    end
end
doesExist = false;

function [doesExist, lineNum] = cellTypeExist(handles, type, cell, val)
%Checks if cell type exists and returns the line number in the file.
%If cell is provided, additionally checks at provided cell.
%If val is provided, additionally checks if val is same for
%data_lines{i}{4}.
fid = fopen(handles.gui_helper.scenario_file, 'r');
data = fread(fid, '*char')';
fclose(fid);
data = regexp(data, {'\n'}, 'split');
data_lines = regexp(data{1}, ',', 'split');
data_len = length(data{1});
for i=2:data_len
    if length(data_lines{i}) < 3
        continue;
    end
    if strcmp(data_lines{i}{3},type)
        if nargin < 3
            doesExist = true;
            lineNum = i;
            return
        elseif str2double(data_lines{i}{1}) == cell(1) ...
                && str2double(data_lines{i}{2}) == cell(2)
            if nargin < 4
                doesExist = true;
                lineNum = i;
                return
            elseif ischar(val)
                if strcmp(data_lines{i}{4}, val)
                    doesExist = true;
                    lineNum = i;
                    return
                end
            elseif isnumeric(val)
                if str2double(data_lines{i}{4}) == val
                    doesExist = true;
                    lineNum = i;
                    return
                end
            end
        end
    end
end
doesExist = false;
lineNum = NaN;

function newFile(filename)
% Creates new file and writes header information.
fid = fopen(filename, 'w');
fwrite(fid, ['cellx, celly, type, args, ...',char(10)]);
fclose(fid);


function deleteLine(handles, line_num)
% Reads file contents as data, remove line from data and write back to file
% If line_num = -1 deletes last line.

startNewLine(handles) % make sure file ends in a new line.
fid = fopen(handles.gui_helper.scenario_file, 'r');
data = fread(fid);
fclose(fid);
newline_indices = 1:length(data);
newline_indices = newline_indices(data==10); %10 is '\n'
if line_num == -1 % delete last line
    line_num = length(newline_indices);
end
if line_num >= 2 && line_num <= length(newline_indices)
    data_out = [data(1:newline_indices(line_num-1)-1)',data(newline_indices(line_num):end)'];
else
    return
end
fid = fopen(handles.gui_helper.scenario_file, 'w');
fwrite(fid, data_out);
fclose(fid);

% XXXXXXXXXXXXXXX
function vehicle_button_Callback(hObject, eventdata, handles)
if ~isempty(handles.gui_helper)
    if(roadCellExist(handles, handles.gui_helper.cursor_cell))
        startNewLine(handles); % make sure start at new line.
        fid = fopen(handles.gui_helper.scenario_file, 'a');
        
        handles.gui_helper.setVehicleStartStateVals(handles.vehicle_start_state_gui_vals);
        fprintf(fid, '%d,%d,vehicle,%.3f,%.3f,%.3f,%.3f\n', [handles.gui_helper.cursor_cell, handles.gui_helper.vehicle_start_state]);
        fclose(fid);
        handles.gui_helper.refresh();
    end
        
end

function vehicle_start_x_Callback(hObject, eventdata, handles)
handles.vehicle_start_state_gui_vals(1) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function vehicle_start_x_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

handles.vehicle_start_state_gui_vals(1) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function vehicle_start_y_Callback(hObject, eventdata, handles)
handles.vehicle_start_state_gui_vals(2) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function vehicle_start_y_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

handles.vehicle_start_state_gui_vals(2) = str2double(get(hObject,'String'));
guidata(hObject, handles);



function vehicle_start_th_Callback(hObject, eventdata, handles)
handles.vehicle_start_state_gui_vals(3) = str2double(get(hObject,'String'));
guidata(hObject, handles);

function vehicle_start_th_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

handles.vehicle_start_state_gui_vals(3) = str2double(get(hObject,'String'));
guidata(hObject, handles);



function vehicle_start_v_Callback(hObject, eventdata, handles)
handles.vehicle_start_state_gui_vals(4) = str2double(get(hObject,'String'));
guidata(hObject, handles);


function vehicle_start_v_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

handles.vehicle_start_state_gui_vals(4) = str2double(get(hObject,'String'));
guidata(hObject, handles);
