function PsychPaidSupportAndServices(mininag)
%
% If you require priority support regarding Psychtoolbox, or custom feature
% development (or if you want to buy a Psychtoolbox themed coffee mug, bag or shirt)
% go to the following website which provides such services:
%
% https://www.psychtoolbox.net
%
% For priority support on the user forum or GitHub issue tracker, buy a
% "community membership with priority support".
%
% 1. As part of your purchase, you will receive a document with a printed
%    "Order Id" and a printed "License key".
%
% 2. Next you can run *this* function PsychPaidSupportAndServices in Octave or
%    Matlab. The function will ask you if you need priority support and do have
%    an active license key to prove your community membership. Answer "y" for yes.
%
% 3. Next the function will ask you about your "Order Id" and "License key".
%    Please enter that info that you got from step 1.
%
% 4. The function will print out an "authentication token", a string of letters and
%    numbers. Now you can post your question on the Psychtoolbox user forum at
%    https://psychtoolbox.discourse.group or open a new issue for bugs and feature
%    requests on our GitHub issue tracker at https://github.com/Psychtoolbox-3/Psychtoolbox-3/issues
%
%    Please add the "authentication token" to your forum question or GitHub issue.
%    This will prove to us that you deserve priority support for your question or
%    issue. Please note that initial activation of your license key may take 5-10
%    days after date of purchase, so do not buy the priority support last minute,
%    when the "house is already burning", but ahead of time, like you would do
%    with a fire insurance.
%
%
% For more detailed background information about Psychtoolbox's need for funding, read on:
%
% Continued development, improvement, maintenance and support of
% Psychtoolbox itself, and also improvement of the various open-source
% software components on which Psychtoolbox and other neuroscience toolkits
% (e.g., PsychoPy) critically depend, including improvements to the Linux
% operating system as the strongest and most high quality foundation for
% demanding stimulation and data collection paradigms, requires a lot of
% highly qualified and highly focused work.
%
% This work is currently (year 2006 - present) mostly carried out by Mario
% Kleiner, who is now employed to do this work by the Medical Innovations
% Incubator GmbH (MII) in Tuebingen, Germany ( https://www.mi-incubator.com ).
% The MII belongs by 100% to the non-profit foundation for medical
% innovations ( http://www.mi-foundation.org ) in Tuebingen.
%
% In order to fund Mario's work and provide him with the resources to do
% this job, the MII offers different types of paid services around
% Psychtoolbox and the use of Linux for neuroscience, among them a
% "Psychtoolbox community membership with priority support".
%
% Your lab can now financially contribute to Psychtoolbox sustainability,
% upkeep and continued improvement, by once a year buying such a community
% membership for a modest fee. This membership entitles you to some
% priority support for questions regarding efficient use of Psychtoolbox,
% questions regarding the resolution of issues you may have with it, fixing
% of bugs you may encounter, and feature requests. MII also offers paid
% feature development and other commercial services.
%
% Please visit the following website, operated by MII, for our offering of
% commercial development services, and for the community membership with
% paid priority support:
%
%
% https://www.psychtoolbox.net
%
%
% The membership allows you to get your voice heard by the developers
% regarding future feature development, as well as preferential treatment
% on the public Psychtoolbox user forum and GitHub issue tracker. Spare
% income generated by your membership fee, that does not have to be used
% to process priority requests made individually by you, will be used to
% fund general development and upkeep of Psychtoolbox and its ecosystem. In
% other words, it contributes to / acts as an insurance that allows
% Psychtoolbox to be around and in good shape years into the future.
%
% To clarify: Psychtoolbox itself will stay freely downloadable and useable
% by anyone, and stay fully accessible as open-source software, by anyone
% for any purpose. Anybody able and willing to contribute code and ideas of
% sufficiently high quality is invited to contribute to the open-source
% code, the documentation on our public community website and Wiki
% http://psychtoolbox.org, and to participate and help each other on the
% public community forum https://psychtoolbox.discourse.group.
%
% Faster support on the forum or the bug trackers, or of any support at all
% in times of high developer workload will be reserved to paying community
% members.
%
% Thanks for your participation and support!
%

% Mini advert requested by some caller, e.g., PsychtoolboxPostInstallRoutine?
if exist('mininag', 'var') && (mininag > 0)
    fprintf('\n');

    % mininag 2 if called from an error handler, mininag 1 if called from
    % general setup code:
    if mininag == 2
        fprintf('NOTE: You may want to acquire paid priority support for future issues like this.\n');
    else
        fprintf('IMPORTANT NEWS:\n\n');
        fprintf('You can now financially contribute to Psychtoolbox sustainability, upkeep and continued\n');
        fprintf('improvement by buying a community membership, which also includes some priority support\n');
        fprintf('for questions regarding its use, or issues you may have with it. We also offer paid\n');
        fprintf('feature development and other useful commercial services.\n');
    end

    fprintf('Please type ''PsychPaidSupportAndServices'' to learn more.\n');
    fprintf('\n\n');

    return;
end

% Nope, full request by user for information:
try
    fid = fopen([PsychtoolboxConfigDir 'welcomemsgdone'], 'w');
    fclose(fid);
catch
end

more on;
help PsychPaidSupportAndServices;
more off;

% Check if user wants to file a support request:
fprintf('\n\n');
answer = input('Do you need priority support now and have an active license key [y/n]? ', 's');
if ~strcmpi(answer, 'y')
    fprintf('A community membership with priority support can be bought as described above. Bye.\n');
    return;
end

% Ok, our valued community member wants support now. Guide them through the process:
orderId = '';
while isempty(orderId)
    orderId = upper(input('Please enter the Order Id of your license: ', 's'));
    if length(orderId) ~= 8 || ~all(isstrprop(orderId, 'alphanum'))
        fprintf('Order Id seems to be invalid: It must be 8 letters or numbers, e.g., XS92UVY3\n');
        orderId = '';
    end
end

% Get the date and time string as 2nd component:
requestTimeDate = sprintf('%i', round(clock));

licenseKey = '';
while isempty(licenseKey)
    licenseKey = upper(input('Please enter the license key: ', 's'));
    if length(licenseKey) ~= 35 || ~all(isstrprop(licenseKey([1:5, 7:11, 13:17, 19:23, 25:29, 31:35]), 'alphanum')) || ~strcmp(licenseKey([6, 12, 18, 24, 30]), '-----')
        fprintf('The license key seems to be invalid: It must be 30 letters or numbers in dash separated groups of five, e.g.,\n');
        fprintf('2BQR7-R5ZQP-SA36G-RAVDJ-ABZBM-PKKFJ\n\n');
        licenseKey = '';
    end
end

% Assemble the to-be-hashed string:
publicString = [orderId '-' requestTimeDate];
hashSrcString = [publicString '-' licenseKey];

% Hash it with SHA-256:
% fprintf('\nThe following string will be SHA-256 hashed: %s\n\n', hashSrcString);
hashString = computeSHA256(hashSrcString);

% Assemble final token for public posting at user forum, issue tracker etc.:
authToken = [publicString ':' hashString];
fprintf('\n\nPlease add the following string to your request when\n');
fprintf('asking for support on the Psychtoolbox user forum\n');
fprintf('[ https://psychtoolbox.discourse.group ]\n');
fprintf('or on the Psychtoolbox-3 GitHub issue tracker\n');
fprintf('[ https://github.com/Psychtoolbox-3/Psychtoolbox-3/issues ]\n');
fprintf('to prove that you are eligible for priority support:\n');
fprintf('========================================================================================\n\n');
fprintf('%s\n\n', authToken);
fprintf('========================================================================================\n\n');

% Validation code for the above:
if 0
    % Disassemble into pieces:
    eOrderId = authToken(1:8)
    epublicStringHashSep = strfind(authToken, ':');
    epublicString = authToken(1:epublicStringHashSep-1)
    ehashString = authToken(epublicStringHashSep+1:end)
    % Here we'd use eOrderId to lookup licenseKey in our DB.
    % Then reassemble source string for hashing:
    ehashSrcString = [epublicString '-' licenseKey]
    % Hash it, and compare our local hash against the one provided in public authToken:
    bingo = strcmp(ehashString, computeSHA256(ehashSrcString))
end

return;

% Embedded SHA-256 implementation. This is the same as PsychComputeSHA(msg, '256'),
% but embedded here to make PsychPaidSupportAndServices() self-contained.
function rethash = computeSHA256(msg)
    shaId = '256';
    if exist('hash', 'builtin')
        % Octave builtin
        rethash = hash(['SHA' shaId], msg);
    else
        md = javaMethod('getInstance', 'java.security.MessageDigest', ['SHA-' shaId]);
        rethash = sprintf('%2.2x', typecast(md.digest(uint8(msg)), 'uint8')');
    end
return;
