% ---
% class ClipSimGraph
% Directed graph representing comparative clip similarities.
%
% 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
% 
% The Edges thus represent the (are nearer to each othen than) 
% expression
% ---

classdef ClipSimGraph < ClipPairGraph

% ---
%  the methods
% ---
methods

    
% constructor of the graph
function G = ClipSimGraph(comparison, comparison_ids)
    
    % ---
    % handle manual input
    % ---
    
    if nargin == 1
        % ---
        % this uses an imput grpaph
        % to create a new MD graph
        % ---
        
        G = ClipSimGraph();

        % ---
        % Add the input graph to the empty one
        % ---
        G.add_graph(comparison);
        
        % ---
        % TODO: Copy Clip Pair Information if neccessary
        % this is by now a handle copy
        % ---
        clas = cat(1, class(comparison), superclasses(comparison));
        if strcellfind(clas, 'ClipPairGraph')
            
            G.vid_map = comparison.vid_map;
        end
        
    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;
                
                % ---
                % TODO: how to determine the weight?
                % There are two options: relative in the triple
                % and counting absolute hits.
                % first we go for the relative ones.
                % The other is implemented in ClipSimGraphMulti
                % ---
                
                % ---
                % add an edge saying sim(a,b) > sim(a,c)
                % ---
                G.add_edge(clips(a), clips(b), clips(c), votes(c) / (sum(votes))); 
               
                % ---
                % every outlier vote results in two
                % dissimilarity equations
                % ---
                
                % edge 2
                G.add_edge(clips(b), clips(a), clips(c), votes(c) / (sum(votes)));

            end

        end
        end
    end

end
    
% end constructor function


function [weights, a, b, c] = similarities(G)
    % ---
    % returns the weights of edges meaning sim(a,b) > sim(a,c)
    % ---    
    % get edge weights
    [weights, a, b, c] = edges(G);
end

% ---
% add an edge saying sim(a,b) > sim(a,c)
% ---
% function add_edge(G, a, b, c, weight)

function remove_edge(G, a, b, c)

    if nargin == 4
        V1 = add_node(G, a, b);
        V2 = add_node(G, a, c);
        
    elseif nargin == 3
        V1 = a;
        V2 = b;
    end

    % ---
    % call superclass
    % --- 
    remove_edge@DiGraph(G, V1, V2);
 end  
 
function set_edge(G, a, b, c, weight)
    if nargin == 5
        V1 = add_node(G, a, b);
        V2 = add_node(G, a, c);
        
    elseif nargin == 4
        V1 = a;
        V2 = b;
        weight = c;
    end

    % ---
    % call superclass
    % --- 
    set_edge@DiGraph(G, V1, V2, weight);
end  

% ---
% simple mix of two sets of info about the same
% nodes: mean.
% NOTE: if there's more than two infos, the earlier
% information will loose influence
% ---
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 Edge to weight
        G.E(V1, V2) = (G.E(V1, V2) + weight) /2;

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

        error 'nodes not found';
    end
end       
end
end


