function [A, B, X, unfilteredA, unfilteredB] = solve(pRfb, pSoundsources, pTrackingParameter, pToaData, pSatData, pLeapsecondsMatrix, pOffsetsParameter, pSoundvelocity)
%UNTITLED Summary of this function goes here
%   Detailed explanation goes here

%% Construct matrices A, B and C
[unfilteredA, unfilteredB, unfilteredC] = artoa.offsets.createCalculationTables( ...
    pRfb, ...
    pSoundsources, ...
    pTrackingParameter, ...
    pToaData, ...
    pSatData, ...
    pSoundvelocity, ...
    pLeapsecondsMatrix ...
);

%% Subtract all known offsets
[B] = artoa.offsets.subtractKnownOffsets( ...
    unfilteredA, ...
    unfilteredB, ...
    pOffsetsParameter.offsets ...
);

%% Subtract all known drifts
[B] = artoa.offsets.subtractKnownDrifts( ...
    unfilteredA, ...
    B, ...
    pOffsetsParameter.offsets ...
);

%% Optimize matrices for calculation
[A, unfilteredA] = artoa.offsets.filterCalculationTables( ...
    unfilteredA, ...
    pOffsetsParameter.offsets ...
    );

%% Subtract window start and soundsource reference time
B.toa = B.toa - unfilteredC.ReferenceTime;

%% Use soundspeed
if ~isnan(pOffsetsParameter.soundspeed{'Soundspeed', 'Empirical'})
    if isempty(A)
        return; % nothing to be done, everything is given and soundspeed is fixed
    end
    
    % Distances are in km, soundspeed m/s
    B.toa = B.toa - A{:, 'Distances'} * (pOffsetsParameter.soundspeed{'Soundspeed', 'Empirical'} / 1000);
    A.Distances = [];
end

%% Solve it!
X = A{:, :} \ B.toa;

%% Apply row names to X
if isrow(X)
    X = X';
end
X = table(X, 'VariableNames', {'Value'}, 'RowNames', A.Properties.VariableNames);
% Rename Distance column to Soundspeed
varNames = X.Properties.RowNames;
for i = 1:length(varNames)
    if strcmp(varNames{i}, 'Distances')
        X.Properties.RowNames{i} = 'Soundspeed';
        X{'Soundspeed', 'Value'} = 1 / X{'Soundspeed', 'Value'};
    end
end

end

