import formatDistance from 'date-fns/formatDistance';
import SourceCommitIcon from 'mdi-react/SourceCommitIcon';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { DecoratedTextLines } from '../../components/DecoratedTextLines';
import { ResultContainer } from '../../components/ResultContainer';
import { GitRefTag } from '../../repo/GitRefTag';
import { RepoLink } from '../../repo/RepoLink';
import { eventLogger } from '../../tracking/eventLogger';
import { UserAvatar } from '../../user/UserAvatar';
import { toPrettyBlobURL } from '../../util/url';
export const CommitSearchResult = (props) => {
    const telemetryData = {
        preview_type: props.result.diffPreview ? 'diff' : 'message',
    };
    const logClickOnPerson = () => eventLogger.log('CommitSearchResultClicked', { commit_search_result: Object.assign({}, telemetryData, { target: 'person' }) });
    const logClickOnMessage = () => eventLogger.log('CommitSearchResultClicked', {
        commit_search_result: Object.assign({}, telemetryData, { target: 'message' }),
    });
    const logClickOnTag = () => eventLogger.log('CommitSearchResultClicked', {
        commit_search_result: Object.assign({}, telemetryData, { target: 'tag' }),
    });
    const logClickOnCommitID = () => eventLogger.log('CommitSearchResultClicked', {
        commit_search_result: Object.assign({}, telemetryData, { target: 'commit-id' }),
    });
    const logClickOnTimestamp = () => eventLogger.log('CommitSearchResultClicked', {
        commit_search_result: Object.assign({}, telemetryData, { target: 'timestamp' }),
    });
    const logClickOnText = () => eventLogger.log('CommitSearchResultClicked', {
        commit_search_result: Object.assign({}, telemetryData, { target: 'text' }),
    });
    const title = (React.createElement("div", { className: "commit-search-result__title" },
        React.createElement(RepoLink, { repoPath: props.result.commit.repository.name, to: props.result.commit.tree
                ? props.result.commit.tree.canonicalURL
                : props.result.commit.repository.url }),
        React.createElement(Link, { to: props.result.commit.url, className: "commit-search-result__title-person", onClick: stopPropagationToCollapseOrExpand, onMouseDown: logClickOnPerson },
            React.createElement(UserAvatar, { user: props.result.commit.author.person, size: 32 }),
            ' ',
            props.result.commit.author.person.displayName),
        React.createElement(Link, { to: props.result.commit.url, className: "commit-search-result__title-message", onClick: stopPropagationToCollapseOrExpand, onMouseDown: logClickOnMessage }, commitMessageSubject(props.result.commit.message) || '(empty commit message)'),
        React.createElement("span", { className: "commit-search-result__title-signature" },
            uniqueRefs([...props.result.refs, ...props.result.sourceRefs]).map((ref, i) => (React.createElement(GitRefTag, { key: i, gitRef: ref, onMouseDown: logClickOnTag }))),
            React.createElement("code", null,
                React.createElement(Link, { to: props.result.commit.url, onClick: stopPropagationToCollapseOrExpand, onMouseDown: logClickOnCommitID }, props.result.commit.abbreviatedOID)),
            ' ',
            React.createElement(Link, { to: props.result.commit.url, onClick: stopPropagationToCollapseOrExpand, onMouseDown: logClickOnTimestamp }, formatDistance(props.result.commit.author.date, new Date(), {
                addSuffix: true,
            })))));
    const expandedChildren = [];
    if (props.result.messagePreview) {
        expandedChildren.push(React.createElement(DecoratedTextLines, { key: "messagePreview", className: "file-match__item commit-search-result__item commit-search-result__item-message-preview", value: props.result.messagePreview.value.split('\n'), highlights: props.result.messagePreview.highlights, lineClasses: [{ line: 1, className: 'strong' }], onMouseDown: logClickOnText }));
    }
    if (props.result.diffPreview) {
        const commonCtx = {
            repoPath: props.result.commit.repository.name,
        };
        // lhsCtx and rhsCtx need the cast because their values at const init time lack
        // the filePath field, which is assigned as we iterate over the lines below.
        const lhsCtx = Object.assign({}, commonCtx, { commitID: props.result.commit.oid + '~', rev: props.result.commit.oid + '~' });
        const rhsCtx = Object.assign({}, commonCtx, { commitID: props.result.commit.oid, rev: props.result.commit.oid });
        // Omit "index ", "--- file", and "+++ file" lines.
        const lines = props.result.diffPreview.value.split('\n');
        const lineClasses = [];
        let ignoreUntilAtAt = false;
        for (const [i, line] of lines.entries()) {
            if (ignoreUntilAtAt && !line.startsWith('@@')) {
                lineClasses.push({ line: i + 1, className: 'hidden' });
                continue;
            }
            else {
                ignoreUntilAtAt = false;
            }
            if (line.startsWith('diff ')) {
                ignoreUntilAtAt = true;
                // Simplify from "diff --git origname newname".
                const [origName, newName] = line.replace(/^diff --git /, '').split(' ');
                let simplerLine;
                if (origName === newName) {
                    simplerLine = origName;
                }
                else {
                    simplerLine = `${origName} -> ${newName} (renamed)`;
                }
                lines[i] = simplerLine;
                lhsCtx.filePath = origName;
                rhsCtx.filePath = newName;
                lineClasses.push({ line: i + 1, className: 'file-header', url: toPrettyBlobURL(rhsCtx) });
            }
            else if (line.startsWith('@@')) {
                // TODO(sqs): a bit hacky getting the position
                try {
                    const m = line.match(/^@@ -(\d+),.*\+(\d+)/);
                    if (m) {
                        if (m[1]) {
                            const lhsLine = parseInt(m[1], 10);
                            lhsCtx.position = { line: lhsLine - 1, character: 0 };
                        }
                        if (m[2]) {
                            const rhsLine = parseInt(m[2], 10);
                            rhsCtx.position = { line: rhsLine - 1, character: 0 };
                        }
                    }
                }
                catch (err) {
                    // TODO(sqs)
                    console.error(err);
                }
                lineClasses.push({ line: i + 1, className: 'hunk-header', url: toPrettyBlobURL(rhsCtx) });
            }
            else {
                if (rhsCtx.position && rhsCtx.position.line) {
                    if (!line.startsWith('+')) {
                        lhsCtx.position.line++;
                    }
                    if (!line.startsWith('-')) {
                        rhsCtx.position.line++;
                    }
                }
                if (line.startsWith('+')) {
                    lineClasses.push({ line: i + 1, className: 'added', url: toPrettyBlobURL(rhsCtx) });
                }
                else if (line.startsWith('-')) {
                    lineClasses.push({
                        line: i + 1,
                        className: 'deleted',
                        url: toPrettyBlobURL(lhsCtx),
                    });
                }
            }
        }
        expandedChildren.push(React.createElement(DecoratedTextLines, { key: "diffPreview", className: "file-match__item commit-search-result__item commit-search-result__item-diff-preview", value: lines, highlights: props.result.diffPreview.highlights, lineClasses: lineClasses, onMouseDown: logClickOnText }));
    }
    return (React.createElement(ResultContainer, { collapsible: true, defaultExpanded: true, icon: SourceCommitIcon, title: title, expandedChildren: expandedChildren }));
};
function commitMessageSubject(message) {
    const eol = message.indexOf('\n');
    return eol === -1 ? message : message.slice(0, eol);
}
function stopPropagationToCollapseOrExpand(e) {
    e.stopPropagation();
}
function uniqueRefs(refs) {
    const seenName = new Set();
    const uniq = [];
    for (const ref of refs) {
        if (!seenName.has(ref.name)) {
            uniq.push(ref);
            seenName.add(ref.name);
        }
    }
    return uniq;
}
//# sourceMappingURL=CommitSearchResult.js.map