classdef Grid < handle

    properties
        parent_cell = [];
        parent_grid = [];
        cells = [];
        split_pb = [];
        num_cells = 0;
        grid_index = 0;
        rGrid = [];
        new_cell_pb = [];
        delete_cell_pb = [];
    end
    
    methods
        %% Grid
        %    constructor
        % inputs:
        %   index:integer - Grid's index
        %   p_cell:Cell - Parent cell
        % outputs:
        %   n:Cell - created cell
        function n = Grid(index,p_cell)
            n.grid_index = index;
            n.parent_cell = p_cell;
        end
        
        %% set_rGrid
        %    set the reference to the Results grid
        % inputs:
        %   obj:Grid - current Grid object
        %   r:RGrid - result Grid
        % outputs:
        %   none
        function [] = set_rGrid(obj,r)
            obj.rGrid = r;
        end
        
        %% new_Cell
        %    creates a new cell in the current grid.
        % inputs:
        %   obj:Grid - current Grid object
        % outputs:
        %   none
        function [] = new_Cell(obj)
           cell = Cell(obj.num_cells+1,obj);
            obj.num_cells = obj.num_cells + 1;
            obj.cells = [obj.cells cell];
            % refresh the rGrid so that a new results cell is created
            if(~isempty(obj.rGrid))
                obj.rGrid.refresh;
            end
        end
        
        %% delete_Cell
        %    deletes the last cell in the grid, also deletes an associated
        %    new grid push button,
        %    TODO, need to implement the case where last cell is deleted.
        % inputs:
        %   obj:Grid - current Grid object
        % outputs
        %   none
        function [] = delete_Cell(obj)
            
           
           last_cell = obj.num_cells;
           obj.rGrid.delete_g2s(obj.cells(end));
           delete(obj.cells(end).cond)
           obj.cells(end).cond = []
           delete(obj.cells(end).grid_pb);
           obj.cells(end).grid_pb = []
           delete(obj.cells(end))
           obj.cells(end) = [];
           if(~isempty(obj.rGrid))
                obj.rGrid.refresh;
            end
        end
    
        
        %% max_width
        %    determines the maximum width from a current grid, the maximum
        %    widht represents the number of levels of subgrids from a given
        %    grid.
        % inputs:
        %   obj:Grid - current Grid object
        % outputs:
        %   m:integer - value representing the maximum width from the
        %   current grid.
        function m = max_width(obj,width)
            temp = []
            for i=1:size(obj.cells,2)
                if (~isempty(obj.cells(i).subgrid))
                    temp = [temp obj.cells(i).subgrid.max_width(width+1)];
                else
                    temp = [temp width];
                end
                
            end
            m = max(temp);
        end
        
        %% set_widths
        %    sets the widths for each of the cells and subcells in a grid.
        %    the width of a cell is equal to the max width of the previous
        %    level - 1 if the cell has no subgrids, or 1 if the cell has a
        %    subgrid.
        % inputs:
        %   obj:Grid - current Grid object
        % outputs:
        %   none
        function [] = set_widths(obj,max_width)
            for i=1:size(obj.cells,2)
                if (~isempty(obj.cells(i).subgrid))
                    obj.cells(i).subgrid.set_widths(max_width-1);
                    obj.cells(i).width = 1;   
                else
                    obj.cells(i).width = max_width;
                end                
            end
        end
        
        %% set_heights
        %    sets the heights for each of the cells and subcells of a grid,
        %    uses the cells cal_height method to determine what the heights
        %    should be.
        % inputs:
        %   obj:Grid - current Grid object
        %   edit:boolean - current value of the edit toggle.
        % outputs:
        %   none
        function [] = set_heights(obj,edit)
            for i = 1:size(obj.cells,2)
                if (~isempty(obj.cells(i).subgrid))
                    obj.cells(i).subgrid.set_heights(edit);
                end
                obj.cells(i).height = obj.cells(i).cal_height(edit);
            end
        
        end
        
        %% set_pb
        %    create the new cell push button
        % inputs:
        %   obj:Grid - current Grid object
        % outputs:
        %   none
        function [] = set_pb(obj,fig,pos)
            if(isempty(obj.new_cell_pb) || ~ishghandle(obj.new_cell_pb))
            obj.new_cell_pb = uicontrol('style','push',...
                'units','pix',...
                'string','new',...
                'HorizontalAlign','left',...
                'Parent',fig,...
                'position',pos,...
                'callback',@(src,event)pb_new_call(obj,src,event));
            else
                set(obj.new_cell_pb,'position',pos);
            end
        end
        
        %% set_delete_pb
        %    create the delete cell push button
        % inputs:
        %   obj:Grid - current Grid object
        % outputs:
        %   none
        function [] = set_delete_pb(obj,fig,pos)
            if(isempty(obj.delete_cell_pb) || ~ishghandle(obj.delete_cell_pb))
            obj.delete_cell_pb = uicontrol('style','push',...
                'units','pix',...
                'string','delete',...
                'HorizontalAlign','left',...
                'Parent',fig,...
                'position',pos,...
                'callback',@(src,event)pb_delete_call(obj,src,event));
            else
                set(obj.delete_cell_pb,'position',pos);
            end
        end
        
        %% pb_new_call
        %    call back function for the new cell push button. When button
        %    is pressed a new cell object is created in the current grid 
        %    and the table is redrawn
        % inputs:
        %   obj:Grid - current Grid object
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs:
        %   none
        function [] = pb_new_call(obj,src,event)
           gui = get(src,'userdata');
            obj.new_Cell;
            gui.reset_wh();
            %gui.draw_grid2(gui.Grid2);
            gui.draw_allgrids(0);
            if size(obj.cells,2) > 1
                set(obj.delete_cell_pb,'Enable','on');
            else
                set(obj.delete_cell_pb,'Enable','off');
            end
            
        end
        
        %% pb_delete_call
        %    callback function for when user clicks on the delete cell
        %    button.
        % inputs:
        %   obj:Grid - current Grid object
        %   src:double - source of the callback calling
        %   event:eventdata - event that triggered the callback
        % outputs:
        %   none
         function [] = pb_delete_call(obj,src,event)
           gui = get(src,'userdata');
        
           deleted_cell = obj.cells(end)
            % button could be pressed in the left or top grid so we need to
            % try to remove the result cell associated with either case.
            obj.rGrid.delete_g2s(deleted_cell);
            obj.rGrid.delete_g1s(deleted_cell);
            deleted_cell.delete_Cell
            obj.cells(end) = [];
   
           if size(obj.cells,2) == 0
             if (~isempty(obj.parent_cell))
                obj.parent_cell.subgrid = [];
                obj.parent_cell.pb_flag = 1;
                delete(obj.new_cell_pb);
                delete(obj.delete_cell_pb);
                obj.rGrid.refresh;
             end
           end
           if size(obj.cells,2) == 1 && isempty(obj.parent_cell)
            set(obj.delete_cell_pb,'Enable','off');
           end
            gui.reset_wh();
            gui.draw_allgrids(0);
           
           
         end
        
         %% deep_delete
         %    deletes an entire grid as well as all the subgrids associated
         %    with it.
         % inputs:
         %   obj:Grid - current Grid object
         % outputs:
         %   none
         function [] = deep_delete(obj)
             % loop through each cell and delete the associated result
             % cells and call delete_Cell on each of the cells, which will
             % then call deep_delete on its subgrids.
             for i=size(obj.cells,2):-1:1
                 obj.rGrid.delete_g2s(obj.cells(i));
                 obj.cells(i).delete_Cell;
                 obj.cells(i) = [];
             end
             delete(obj.new_cell_pb)
             delete(obj.delete_cell_pb)
             obj.new_cell_pb = [];
             obj.delete_cell_pb = [];
             
         end
         
         
         function [] = clone(obj,dest_grid,index,p_cell)
            for i=1:size(obj.cells,2)
                dest_grid.new_Cell();
                dest_grid.cells(i).cond_text = obj.cells(i).cond_text
                if (~isempty(obj.cells(i).subgrid))
                    dest_grid.cells(i).subgrid = Grid(dest_grid.cells(i).cell_index,dest_grid.cells(i))
                    dest_grid.cells(i).subgrid.set_rGrid(dest_grid.cells(i).parent_grid.rGrid);
                   obj.cells(i).subgrid.clone(dest_grid.cells(i).subgrid,obj.cells(i).subgrid.grid_index,dest_grid.cells(i))
                else
                    
                end
                
            end
         end
    end
    
    
end

