% ---
% class ClipSimGraphMulti
% Directed MultiGraph representing comparative clip similarities.
% EACH pair of vertices has multiple directed edges connecting them
%
% each node represents a pair of clips,
% an edge (a,b) -> (a,c) is present if there is at least one
% users judging clip a more similar to clip b than to clip c
% 
% Each edge thus represent a single (are nearer to each othen than) 
% expression
% ---

classdef ClipSimGraphMulti < ClipSimGraph & handle

    
properties

end

% ---
%  the methods
% ---
methods
        
% constructor of the graph
function G = ClipSimGraphMulti(comparison, comparison_ids)
    
    if nargin == 0
        % ---
        % empty constructor
        % ---
        
    elseif nargin == 1
        % todo: copy graph if same class
        
        % ---
        % this uses an imput grpaph
        % to create a new MD graph
        % ---
        
        G = ClipSimGraphMulti();

        % ---
        % Add the input graph to the empty one
        % ---
        G.add_graph(comparison);
        
    elseif nargin == 2


        % ---
        % handle automatic or manual input
        % ---
        for i = 1:size(comparison,1)

            % get clips and votes
            clips = comparison_ids(comparison(i,1:3));
            votes = comparison(i,4:6);

            % for each triplet position create an edge reflecting the 
            % absolute and relative voting for this position

            % ---
            % NOTE: we index 0 - 2 to ease the mod
            % calculaton for the remaining indices
            % ---
            for v = 0:2

                % ---
                % has at least one user voted this clip out?
                % If so, treat it as an outlier and determine score
                % ---
                if votes(v+1) > 0

                    a = mod(v+1, 3)+1;
                    b = mod(v+2, 3)+1;
                    c = v+1;


                    % ---
                    % every outlier vote results in two
                    % dissimilarity equations, favored by 
                    % the people who voted for the outlier
                    % ---
                    
                    % edge 1     
                    add_edge(G, clips(a), clips(b), clips(c), votes(v+1));

                    % edge 2
                    add_edge(G, clips(b), clips(a), clips(c), votes(v+1));
                end
            end

        end
    end
    
% end constructor function
end

function out = order(G)
    
   out = sum(G.V);
end

function out = num_edges_multi(G)
    out = sum(sum(G.E));
end

function out = num_edges(G)
    out = sum(sum(G.E ~= 0));
end


 % ---
% NOTE: the weight explains the multiplicity of each
% edge, to correctily describe this, 
% we just count the votes
% ---
function join_edge(G, a, b, c, weight)

    if nargin == 5
        V1 = G.node(a, b);
        V2 = G.node(a, c);
    elseif nargin == 4
        V1 = a;
        V2 = b;
        weight = c;
    end
    
    if  G.edge(V1, V2) ~= 0

        % set add number to Edge index
        G.E(V1, V2) = (G.E(V1, V2) + weight);

        cprint(3, 'edge weight %d %d %d updated \n',a ,b , c) ;
    else

        error 'nodes not found';
    end
end  

% ---
% This eliminates any order-2 cycles,
% by substracting opposing edge counts
% ---
function remove_cycles_length2(G)
    
    G.E = max(0, G.E - G.E');
end
% ---
% TODO: this back-and forth transform is a workaround 
%  avoiding some costly other transformation which would
%  happen during the direct digraph call
% ---

function [Gs, s, id] = connected_components(G, varargin)
    % ---
    % get all connected subgraphs:
    % ---
    G2 = DiGraph(G);
    
    [GsDiGraph, s, id]  = connected_components@DiGraph(G2, varargin{:});
    
    for i = 1:numel(GsDiGraph)
        Gs(i) = ClipSimGraphMulti(GsDiGraph(i));
    end 
end


end

methods (Hidden)
    
end
end
