%% The code block for properties %% 

properties (Access = private)
    placedCards % string array of placed cards
    counter % double as loop counter
end

methods(Static)
    function cards = initialize21Cards()
        deck = ["♠","♥","♦","♣"] + ["A";(2:9)';'10';'J';'Q';'K'];
        shuffledDeck = deck(randperm(numel(deck)));
        picked = shuffledDeck(1:21);
        cards = picked(randperm(21));
    end
end

%% the code block for private methods %%

methods (Access = private)

    function plotCardsFaceUp(app,cards)
        [recPos,txtPos,seq,axisLim] = positionCards(app,cards);
        plotCards(app,recPos,txtPos,seq,axisLim,true)        
    end

    function plotCardsPiled(app,cards)
        [recPos,txtPos,seq,axisLim] = positionCards(app,cards);
        recPos = recPos([1,8,15],:);
        txtPos = txtPos([1,8,15],:);
        seq = seq([7,14,21]);
        plotCards(app,recPos,txtPos,seq,axisLim,true)
    end

    function plotCardsStacked(app,cards)
        [recPos,txtPos,seq,axisLim] = positionCards(app,cards);
        recPos = recPos(8,:);
        txtPos = txtPos(8,:);
        seq = seq(14);
        plotCards(app,recPos,txtPos,seq,axisLim,true)
    end

    function [recPos,txtPos,seq,axisLim] = positionCards(~,cards)
        [n,m] = size(cards);
        recPos = zeros(n*m,4);
        txtPos = zeros(n*m,2);
        seq = [];
        for ii = 1:n
            seq = [seq cards(ii,1:m)];
        end

        origin = [1.5 1];
        w = 1;
        h = 2;
        spacing = 0.2;

        if all([n,m] == 1)
            recPos = [origin w h];
            txtPos = [recPos(:,1)+w/2 recPos(:,2)+h/2];
        else
            for ii = 1:n
                recPos(m*(ii-1)+1:m*ii,1) = origin(1)+(w+spacing)*((1:m)'-1);
                recPos(m*(ii-1)+1:m*ii,2) = origin(2)+(h+spacing)*(ii-1);
                txtPos(m*(ii-1)+1:m*ii,1) = recPos(m*(ii-1)+1:m*ii,1) + w/2;
                txtPos(m*(ii-1)+1:m*ii,2) = recPos(m*(ii-1)+1:m*ii,2) + h/2;
            end
            recPos(:,3) = w;
            recPos(:,4) = h;
        end

        if all([n,m] ~= 1)
            axisLim = ceil(origin(1)+(w+spacing)*m);
            recPos(:,2) = recPos(:,2) + (axisLim-(h+spacing)*n)/2 - origin(2);
            txtPos(:,2) = recPos(:,2) + h/2;
        else
            axisLim = ceil(origin(2) + (h + spacing) * m);
            recPos(:,1) = (axisLim - w)/2;
            recPos(:,2) = (axisLim - h)/2;
            txtPos(:,1) = recPos(:,1) + w/2;
            txtPos(:,2) = recPos(:,2) + h/2;
        end
    end

    function plotCards(app,recPos,txtPos,seq,axisLim,addLabels)
        for ii = 1:size(recPos,1)
            rectangle(app.UIAxes,'Position',recPos(ii,:),'Curvature',0.2,"FaceColor","w")
            color = 'k';
            if contains(seq(ii),["♥","♦"])
                color = 'r';
            end
            text(app.UIAxes,txtPos(ii,1),txtPos(ii,2),seq(ii),"Color",color,"HorizontalAlignment","center","FontSize",16)
        end
        if addLabels
            posY = unique(txtPos(:,2));
            if length(posY) > 1
                text(app.UIAxes,1,posY(1),"Bottom","HorizontalAlignment","center","Rotation",90)
                text(app.UIAxes,1,posY(2),"Middle","HorizontalAlignment","center","Rotation",90)
                text(app.UIAxes,1,posY(3),"Top","HorizontalAlignment","center","Rotation",90)
            else
                text(app.UIAxes,1,posY,"Middle","HorizontalAlignment","center","Rotation",90)
            end
        end
        axis(app.UIAxes,[0 axisLim 0 axisLim])
        if app.counter < 4
            title(app.UIAxes,"Round " + app.counter)
        else
            title(app.UIAxes,"Answer")
        end
        axis(app.UIAxes,'off')
    end

end

%% the code blocks for respective components %%

% Callbacks that handle component events
methods (Access = private)

    % Code that executes after component creation
    function startupFcn(app)
        cards = app.initialize21Cards();
        cards = cards(randperm(21));
        placed = reshape(cards,[3 7]);
        app.counter = 0;
        app.placedCards = placed;
        plotCardsFaceUp(app,placed)
    end

    % Button pushed function: StartOverButton
    function StartOverButtonPushed(app, event)
        app.UIAxes.cla;
        cards = app.initialize21Cards();
        cards = cards(randperm(21));
        placed = reshape(cards,[3 7]);
        app.counter = 0;
        app.placedCards = placed;
        plotCardsFaceUp(app,placed)
    end

    % Selection changed function: WhichRowButtonGroup
    function WhichRowButtonGroupSelectionChanged(app, event)
        selectedButton = app.WhichRowButtonGroup.SelectedObject;
            
        if contains(selectedButton.Text,"Bottom")
            selectedRow = 1;
        elseif contains(selectedButton.Text,"Middle")
            selectedRow = 2;
        elseif contains(selectedButton.Text,"Top")
            selectedRow = 3;
        else
            return
        end
        app.NoneButton.Value = 1;
            
        stacked = restack(selectedRow);
        placed = reshape(stacked,[3 7]);
            
        if app.counter < 4
            app.placedCards = placed;
            app.counter = app.counter + 1;
            app.UIAxes.cla;
            plotCardsFaceUp(app,placed)
        end
        if app.counter == 4
            answer = app.placedCards(2,4);
            app.UIAxes.cla;
            plotCardsFaceUp(app,answer)
        end

        function stacked = restack(selectedRow)
            placed = app.placedCards;
            app.UIAxes.cla;
            plotCardsPiled(app,placed)
            pause(1)
            rows = randperm(3);
            rows = setdiff(rows,selectedRow);
            rows = [rows(1), selectedRow, rows(2)];
            stacked = [placed(rows(1),:),placed(rows(2),:),placed(rows(3),:)];
            app.UIAxes.cla;
            plotCardsStacked(app,placed)
            pause(1)
        end
end