<div x-data="alpineAbilities()" x-init="initPage()">

    <!-- PAGE HEADER -->

    <div x-ref="headerAbilities">
        <h2>Abilities</h2>
        <p>
            An ability is a specific ATT&CK tactic/technique implementation which can be executed on running agents. Abilities will include the command(s) to run, the platforms / executors the commands can run on (ex: Windows / PowerShell), payloads to include, and a reference to a module to parse the output on the Caldera server.
        </p>
    </div>
    <hr>

    <!-- ABILITIES TABLE -->

    <div class="columns">
        <div class="column m-0 is-2 filters">
            <button class="button is-primary is-small is-fullwidth mb-4" @click="createAbility">+ Create an Ability</button>
            <p class="has-text-weight-bold">Filters</p>
            <form>
                <div class="field">
                    <label class="label is-small">Search</label>
                    <div class="control has-icons-left" style="width: 100%;">
                        <input class="input is-small" x-model="searchTerm" type="text" placeholder="Find an ability..." @keyup="filterAbilities()">
                        <span class="icon is-small is-left">
                            <i class="fas fa-search"></i>
                        </span>
                    </div>
                </div>
                <div class="field">
                    <label class="label is-small">Tactic</label>
                    <div class="control">
                        <div class="select is-small is-fullwidth">
                            <select x-model="selectedTactic" x-on:change="filterAbilities()">
                                <option value="">All</option>
                                <template x-for="tactic in tactics">
                                    <option x-bind:value="tactic" x-text="tactic" x-bind:selected="tactic === selectedTactic"></option>
                                </template>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="field">
                    <label class="label is-small">Technique</label>
                    <div class="control">
                        <div class="select is-small is-fullwidth">
                            <select x-model="selectedTechnique" x-on:change="filterAbilities()">
                                <option value="">All</option>
                                <template x-for="technique in techniques">
                                    <option x-bind:value="technique" x-text="technique" x-bind:selected="technique === selectedTechnique"></option>
                                </template>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="field">
                    <label class="label is-small">Plugin</label>
                    <div class="control">
                        <div class="select is-small is-fullwidth">
                            <select x-model="selectedPlugin" x-on:change="filterAbilities()">
                                <option value="">All</option>
                                <template x-for="plugin in plugins">
                                    <option x-bind:value="plugin" x-text="plugin" x-bind:selected="plugin === selectedPlugin"></option>
                                </template>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="field">
                    <label class="label is-small">Platform</label>
                    <div class="control pl-3">
                        <template x-for="platform in platforms">
                            <div>
                                <label class="checkbox mb-2">
                                    <input type="checkbox" x-model="selectedPlatforms[platform]" x-on:change="filterAbilities()">
                                    <span x-text="platform"></span>
                                </label>
                                <br>
                            </div>
                        </template>
                    </div>
                </div>
            </form>
            <button class="button is-small is-fullwidth mb-2" x-show="searchTerm || selectedTactic || selectedTechnique || selectedPlugin" @click="clearFilters()">Clear Filters</button>
            <p class="has-text-centered">
                <strong x-text="filteredAbilities.length" class="pr-1"></strong>
                /
                <span x-text="abilities.length" class="pl-1"></span>&nbsp;
                abilities
            </p>
        </div>
        <div class="column abilities is-10 m-0 is-flex is-flex-wrap-wrap is-align-content-flex-start">
            <div x-show="!isLoaded">
                <p>Please wait, loading...</p>
            </div>
            <template x-for="ability in filteredAbilities" :key="ability.ability_id">
                <div class="box mb-2 mr-2 p-3 ability" @click="selectAbility(ability)">
                    <span class="tag tactic m-0 mb-1" x-text="ability.tactic"></span>
                    <p>
                        <span class="has-text-weight-bold" x-text="ability.name"></span>
                        <span x-text="`(${ability.technique_id})`"></span>
                    </p>
                    <p class="help mb-0" x-text="ability.description"></p>
                    <p class="platforms">
                        <template x-for="platform of getAbilityPlatforms(ability)">
                            <span class="has-tooltip-arrow has-tooltip-left no-underline" x-bind:data-tooltip="platform">
                                <span class="icon is-small"><i class="fab" x-bind:class="if (platform.includes('windows')) return 'fa-windows'; else if (platform.includes('darwin')) return 'fa-apple'; else if (platform.includes('linux')) return 'fa-linux'"></i></span>
                            </span>
                        </template>
                    </p>
                </div>
            </template>
        </div>
    </div>

    <!-- MODALS -->

    <div class="modal" x-bind:class="{ 'is-active': showAbilityModal }">
        <div class="modal-background" @click="showAbilityModal = false"></div>
        <div class="modal-card wide">
            <header class="modal-card-head">
                <p class="modal-card-title"><span x-text="isCreatingAbility ? 'Create' : 'Edit'"></span> an Ability</p>
            </header>
            <section class="ability-detail modal-card-body">
                <template x-if="selectedAbility">
                    <div class="content">
                        <form>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">ID</label>
                                </div>
                                <div class="field-body">
                                    <div class="field has-addons">
                                        <div class="control is-expanded">
                                            <input class="input is-small" x-model="selectedAbility.ability_id" disabled>
                                        </div>
                                        <div class="control">
                                            <a class="button is-small has-tooltip-left has-tooltip-arrow" data-tooltip="Generate New ID" @click="selectedAbility.ability_id = uuidv4()">
                                                <span class="icon is-small"><i class="fas fa-sync"></i></span>
                                            </a>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Name</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control">
                                            <input class="input is-small" x-bind:class="{ 'is-danger': fieldErrors.includes('name') }" x-model="selectedAbility.name">
                                            <p x-show="fieldErrors.includes('name')" class="help is-danger">This field is required.</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Description</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control">
                                            <input class="input is-small" x-bind:class="{ 'is-danger': fieldErrors.includes('description') }" x-model="selectedAbility.description">
                                            <p x-show="fieldErrors.includes('description')" class="help is-danger">This field is required.</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Tactic</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control auto-complete" x-data="{focusSearchResults: true}" @click.outside="focusSearchResults = false; autoFillResults = []">
                                            <input class="input is-small" x-bind:class="{ 'is-danger': fieldErrors.includes('tactic') }" x-model="selectedAbility.tactic" x-on:keyup="searchForAutoFill('tactic')" @click="focusSearchResults = true">
                                            <div class="search-results is-size-7" x-show="autoFillResults && focusSearchResults">
                                                <template x-for="result of autoFillResults" :key="result">
                                                    <p x-show="result !== selectedAbility.tactic" @click="selectedAbility.tactic = result; autoFillResults = []" x-text="result"></p>
                                                </template>
                                            </div>
                                            <p x-show="fieldErrors.includes('tactic')" class="help is-danger">This field is required.</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label is-small">Technique ID</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control auto-complete" x-data="{focusSearchResults: true}" @click.outside="focusSearchResults = false; autoFillResults = []">
                                            <input class="input is-small" x-bind:class="{ 'is-danger': fieldErrors.includes('technique_id') }" x-model="selectedAbility.technique_id" x-on:keyup="searchForAutoFill('technique_id')" @click="focusSearchResults = true">
                                            <div class="search-results is-size-7" x-show="autoFillResults && focusSearchResults">
                                                <template x-for="result of autoFillResults" :key="result">
                                                    <p x-show="result !== selectedAbility.technique_id" @click="selectedAbility.technique_id = result; autoFillResults = []" x-text="result"></p>
                                                </template>
                                            </div>
                                            <p x-show="fieldErrors.includes('technique_id')" class="help is-danger">This field is required.</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Technique Name</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control auto-complete" x-data="{focusSearchResults: true}" @click.outside="focusSearchResults = false; autoFillResults = []">
                                            <input class="input is-small" x-bind:class="{ 'is-danger': fieldErrors.includes('technique_name') }" x-model="selectedAbility.technique_name" x-on:keyup="searchForAutoFill('technique_name')" @click="focusSearchResults = true">
                                            <div class="search-results is-size-7" x-show="autoFillResults && focusSearchResults">
                                                <template x-for="result of autoFillResults" :key="result">
                                                    <p x-show="result !== selectedAbility.technique_name" @click="selectedAbility.technique_name = result; autoFillResults = []" x-text="result"></p>
                                                </template>
                                            </div>
                                            <p x-show="fieldErrors.includes('technique_name')" class="help is-danger">This field is required.</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Singleton</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control mt-2">
                                            <input type="checkbox" x-model="selectedAbility.singleton">
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Repeatable</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control mt-2">
                                            <input type="checkbox" x-model="selectedAbility.repeatable">
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Delete payload</label>
                                </div>
                                <div class="field-body">
                                    <div class="field">
                                        <div class="control mt-2">
                                            <input type="checkbox" x-model="selectedAbility.delete_payload">
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </form>
                        <p class="has-text-centered">Executors</p>
                        <p x-show="fieldErrors.includes('executors')" class="help is-danger">At least one executor is required.</p>
                        <div class="has-text-centered">
                            <button class="button is-small is-primary" @click="addExecutorToAbility('before')">+ Add Executor</button>
                        </div>
                        <br>
                        <template x-for="(executor, index) of selectedAbility.executors" :key="index">
                            <div class="box">
                                <div class="has-text-right">
                                    <button class="delete" @click="selectedAbility.executors.splice(index, 1)"></button>
                                </div>
                                <form>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small">
                                            <label class="label">platform</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field ">
                                                <div class="control">
                                                    <div class="select is-small">
                                                        <select x-model="executor.platform">
                                                            <template x-for="plat of getPlatforms(executor.platform)" :key="plat">
                                                                <option x-bind:value="plat" x-text="plat"></option>
                                                            </template>
                                                        </select>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small">
                                            <label class="label">executor</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field ">
                                                <div class="control">
                                                    <div class="select is-small">
                                                        <select x-model="executor.name">
                                                            <option default disabled>Select an executor...</option>
                                                            <template x-for="exec of getExecutors(executor.platform, executor.name)" :key="exec">
                                                                <option x-bind:value="exec" x-text="exec""></option>
                                                            </template>
                                                        </select>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small">
                                            <label class="label">payloads</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field is-grouped is-grouped-multiline">
                                                <p x-show="executor.payloads.length === 0" class="help">No payloads selected</p>
                                                <template x-for="(payload, index) of executor.payloads">
                                                    <div class="control">
                                                        <div class="tags has-addons">
                                                            <span class="tag is-small is-link" x-text="payload"></span>
                                                            <a class="tag is-delete" x-on:click="executor.payloads.splice(index, 1)"></a>
                                                        </div>
                                                    </div>
                                                </template>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small">
                                            <label class="label"></label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field">
                                                <div class="control">
                                                    <div class="select is-small is-multiple is-fullwidth">
                                                        <select class="select is-multiple" multiple size="6">
                                                            <template x-for="payload of payloads">
                                                                <option x-show="executor.payloads.indexOf(payload) === -1" x-on:click="executor.payloads.push(payload)" x-text="payload"></option>
                                                            </template>
                                                        </select>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small">
                                            <label class="label">command</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field ">
                                                <div class="control">
                                                    <textarea class="textarea is-small code" x-model="executor.command"></textarea>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <template x-for="(requirements, index) of selectedAbility.requirements">
                                        <div class="field is-horizontal">
                                            <div class="field-label is-small">
                                                <label class="label" x-text="index === 0 ? 'requirements': ' '"></label>
                                            </div>
                                            <div class="field-body" style="background-color: var(--primary-color-translucent);">
                                                <div class="field has-addons">
                                                    <div class="control is-expanded">
                                                        <label class="label" for="requirement-module">Requirement Module</label>
                                                        <input id="requirement-module" class="input is-small code" x-model="requirements['module']">
                                                        <label class="label" for="requirement-source">Source</label>
                                                        <input id="requirement-source" class="input is-small code" x-model="requirements['relationship_match'][0]['source']">
                                                        <label class="label" for="requirement-edge">Edge</label>
                                                        <input id="requirement-edge" class="input is-small code" x-model="requirements['relationship_match'][0]['edge']">
                                                        <label class="label" for="requirement-target">[optional] Target</label>
                                                        <input id="requirement-target" class="input is-small code" x-model="requirements['relationship_match'][0]['target']">
                                                    </div>
                                                    <div class="control">
                                                        <a class="button is-small has-tooltip-bottom has-tooltip-arrow" data-tooltip="Remove requirement" @click="selectedAbility.requirements.splice(index, 1)">
                                                            <span class="icon is-small"><i class="fas fa-minus-square"></i></span>
                                                        </a>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </template>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small" x-show="!selectedAbility.requirements.length">
                                            <label class="label">requirements</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field">
                                                <div class="control has-text-right">
                                                    <button type="button" class="button is-small is-primary" @click.stop="selectedAbility.requirements.push({'module': '','relationship_match':[{'source':'', 'edge':'','target':''}]})">+ Add requirements</button>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small">
                                            <label class="label">timeout</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field">
                                                <div class="control">
                                                    <input class="input is-small" type="number" x-model="executor.timeout">
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <template x-for="(cleanup, index) of executor.cleanup">
                                        <div class="field is-horizontal">
                                            <div class="field-label is-small">
                                                <label class="label" x-text="index === 0 ? 'cleanup': ' '"></label>
                                            </div>
                                            <div class="field-body">
                                                <div class="field has-addons">
                                                    <div class="control is-expanded">
                                                        <input class="input is-small code" x-model="executor.cleanup[index]"></input>
                                                    </div>
                                                    <div class="control">
                                                        <a class="button is-small has-tooltip-bottom has-tooltip-arrow" data-tooltip="Remove cleanup command" @click="executor.cleanup.splice(index, 1)">
                                                            <span class="icon is-small"><i class="fas fa-minus-square"></i></span>
                                                        </a>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </template>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small" x-show="!executor.cleanup.length">
                                            <label class="label">cleanup</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field">
                                                <div class="control has-text-right">
                                                    <button type="button" class="button is-small is-primary" @click.stop="executor.cleanup.push('')">+ Add Cleanup Command</button>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <template x-for="(parsers, index) of executor.parsers">
                                        <div class="field is-horizontal">
                                            <div class="field-label is-small">
                                                <label class="label" x-text="index === 0 ? 'parsers': ' '"></label>
                                            </div>
                                            <div class="field-body p-2" style="background-color: var(--primary-color-translucent);">
                                                <div class="field has-addons">
                                                    <div class="control is-expanded">
                                                        <label class="label" for="parser-module">Parser Module</label>
                                                        <input id="parser-module" class="input is-small code" x-model="parsers['module']">
                                                        <label class="label mt-1" for="parser-source">Output Source</label>
                                                        <input id="parser-source" class="input is-small code" x-model="parsers['parserconfigs'][0]['source']">
                                                        <label class="label mt-1" for="parser-edge">Output Edge [optional]</label>
                                                        <input id="parser-edge" class="input is-small code" x-model="parsers['parserconfigs'][0]['edge']">
                                                        <label class="label mt-1" for="parser-target">Output Target [optional]</label>
                                                        <input id="parser-target" class="input is-small code" x-model="parsers['parserconfigs'][0]['target']">
                                                    </div>
                                                    <div class="control">
                                                        <a class="button is-small has-tooltip-bottom has-tooltip-arrow" data-tooltip="Remove parser" @click="executor.parsers.splice(index, 1)">
                                                            <span class="icon is-small"><i class="fas fa-minus-square"></i></span>
                                                        </a>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </template>
                                    <div class="field is-horizontal">
                                        <div class="field-label is-small" x-show="!executor.parsers.length">
                                            <label class="label">parsers</label>
                                        </div>
                                        <div class="field-body">
                                            <div class="field">
                                                <div class="control has-text-right">
                                                    <button type="button" class="button is-small is-primary" @click.stop="executor.parsers.push({'module': '', 'parserconfigs':[{'source':'', 'edge':'','target':''}]})">+ Add parsers</button>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </form>
                            </div>
                        </template>
                        <template x-if="selectedAbility.executors.length > 0">
                            <div class="has-text-centered">
                                <button class="button is-small is-primary" @click="addExecutorToAbility('after')">+ Add Executor</button>
                            </div>
                        </template>
                    </div>
                </template>
            </section>
            <footer class="modal-card-foot">
                <nav class="level">
                    <div class="level-left">
                        <div class="level-item">
                            <button class="button is-primary is-small" @click="deleteAbility()" x-show="!isCreatingAbility">
                                <span class="icon"><i class="fas fa-trash"></i></span>
                                <span>Delete Ability</span>
                            </button>
                        </div>
                    </div>
                    <div class="level-right">
                        <div class="level-item">
                            <button class="button is-small" @click="showAbilityModal = false">Close</button>
                        </div>
                        <div class="level-item">
                            <button class="button is-primary is-small" @click="saveAbility()">
                                <span class="icon"><i class="fas fa-save"></i></span>
                                <span>Save</span>
                            </button>
                        </div>
                    </div>
                </nav>
            </footer>
        </div>
    </div>

</div>

<script>
    function alpineAbilities() {
        return {
            // Core variables
            abilities: [],
            filteredAbilities: [],
            searchTerm: '',
            selectedAbility: '',
            windowHref: '',
            searchQuery: '',
            searchResults: [],
            autoFillResults: [],

            tactics: [],
            selectedTactic: '',
            techniques: [],
            selectedTechnique: '',
            platforms: [],
            selectedPlatforms: {},
            plugins: [],
            selectedPlugin: '',

            allPlatforms: JSON.parse('{{ platforms | tojson }}'),
            payloads: JSON.parse('{{ payloads | tojson }}').sort(),
            isLoaded: false,
            isCreatingAbility: false,

            // Modals
            showAbilityModal: false,

            // Input validation
            requiredFields: ['name', 'description', 'tactic', 'technique_id', 'technique_name', 'executors'],
            fieldErrors: [],

            initPage() {
                apiV2('GET', 'api/v2/abilities').then(async (abilities) => {
                    this.abilities = abilities;
                    this.checkUrlParameters();
                    this.filterAbilities();

                    while (this.$refs.headerAbilities) {
                        await sleep(500);
                        this.checkUrlParameters();
                    }
                }).catch((error) => {
                    toast('Error loading page', false);
                    console.error(error);
                })
            },

            checkUrlParameters() {
                if (window.location.href === this.windowHref) return
                this.windowHref = window.location.href;
                let url = new URL(window.location);
                const urlParams = new URLSearchParams(url.search);

                let selectedPlugin = urlParams.get('plugin');
                if (selectedPlugin) {
                    this.selectedPlugin = selectedPlugin;
                    this.filterAbilities();
                }
            },

            getFilterOptions() {
                this.tactics = [];
                this.techniques = [];
                this.platforms = [];
                this.plugins = [];

                this.abilities.forEach((ability) => {
                    if (!this.tactics.includes(ability.tactic) && (!this.selectedTechnique || `${ability.technique_id} | ${ability.technique_name}` === this.selectedTechnique)) {
                        this.tactics.push(ability.tactic);
                    }
                    if (!this.techniques.includes(`${ability.technique_id} | ${ability.technique_name}`) && (!this.selectedTactic || this.selectedTactic === ability.tactic)) {
                        this.techniques.push(`${ability.technique_id} | ${ability.technique_name}`);
                    }
                    if (!this.plugins.includes(ability.plugin)) {
                        this.plugins.push(ability.plugin);
                    }
                    ability.executors.forEach((exec) => {
                        if (!this.platforms.includes(exec.platform)) this.platforms.push(exec.platform);
                    })
                })

                this.tactics.sort();
                this.techniques.sort();
                this.platforms.sort();
                this.plugins.sort();

                this.platforms.forEach((platform) => {
                    if (this.selectedPlatforms[platform] === undefined) {
                        this.selectedPlatforms[platform] = true;
                    }
                });
            },

            filterAbilities() {
                this.filteredAbilities = this.abilities.filter((ability, index) => {
                    let lcSearchTerm = this.searchTerm.toLowerCase();
                    let matchesSearch = (
                        ability.name.toLowerCase().includes(lcSearchTerm) ||
                        ability.description.toLowerCase().includes(lcSearchTerm) ||
                        ability.tactic.toLowerCase().includes(lcSearchTerm) ||
                        ability.technique_id.toLowerCase().includes(lcSearchTerm) ||
                        ability.technique_name.toLowerCase().includes(lcSearchTerm)
                    );
                    let matchesTactic = (!this.selectedTactic || ability.tactic === this.selectedTactic);
                    let matchesTechnique = (!this.selectedTechnique || `${ability.technique_id} | ${ability.technique_name}` === this.selectedTechnique);
                    let platforms = ability.executors.map((exec) => exec.platform);
                    let matchesPlatform = platforms.some((platform) => this.selectedPlatforms[platform] === undefined || this.selectedPlatforms[platform] === true);
                    let matchesPlugin = (!this.selectedPlugin || ability.plugin === this.selectedPlugin);

                    return matchesSearch && matchesTactic && matchesTechnique && matchesPlatform && matchesPlugin;
                });
                this.getFilterOptions();
                this.isLoaded = true;
            },

            clearFilters() {
                this.searchTerm = '';
                this.selectedTactic = '';
                this.selectedTechnique = '';
                this.selectedPlugin = '';
                this.platforms.forEach((platform) => this.selectedPlatforms[platform] = true);
                this.getFilterOptions();
                this.filterAbilities();
            },

            getAbilityPlatforms(ability) {
                return [...new Set(ability.executors.map((exec) => `${exec.platform} (${exec.name})`))];
            },

            getPlatforms(platform) {
                let plats = Object.keys(this.allPlatforms);
                let index = plats.indexOf(platform);
                if (index !== 0) {
                    plats[index] = plats[0];
                    plats[0] = platform;
                }
                return plats;
            },

            getExecutors(platform, executor) {
                let execs = this.allPlatforms[platform];
                let index = execs.indexOf(executor);
                if (index !== 0) {
                    execs[index] = execs[0];
                    execs[0] = executor;
                }
                return execs;
            },

            searchForAutoFill(field = 'tactic') {
                const results = new Set();
                if (!this.selectedAbility[field]) return;
                this.abilities.forEach((ability) => {
                    if (ability[field].toLowerCase().indexOf(this.selectedAbility[field].toLowerCase()) > -1) {
                        results.add(ability[field]);
                    }
                });
                this.autoFillResults = Array.from(results);
            },

            searchForAbility() {
                this.searchResults = [];
                if (!this.searchQuery) return;
                this.abilities.forEach((ability) => {
                    if (ability.name.toLowerCase().indexOf(this.searchQuery.toLowerCase()) > -1) {
                        this.searchResults.push(ability);
                    }
                });
            },

            selectAbility(ability) {
                this.isCreatingAbility = false;
                this.fieldErrors = [];
                this.selectedAbility = ability;
                this.showAbilityModal = true;
                this.searchResults = [];
            },

            createAbility() {
                this.isCreatingAbility = true;
                this.selectedAbility = {
                    ability_id: uuidv4(),
                    name: '',
                    description: '',
                    tactic: '',
                    technique_id: '',
                    technique_name: '',
                    executors: [],
                    repeatable: false,
                    additional_info: {},
                    privilege: '',
                    singleton: true,
                    buckets: [],
                    requirements: [],
                    access: {},
                    cleanup: []
                };
                this.addExecutorToAbility('before');
                this.showAbilityModal = true;
            },

            saveAbility() {
                this.fieldErrors = validateInputs(this.selectedAbility, this.requiredFields);
                if (this.fieldErrors.length) return;
                let data = this.filterUndefined(this.selectedAbility);
                apiV2('PUT', `/api/v2/abilities/${this.selectedAbility.ability_id}`, data).then((response) => {
                    toast('Saved ability!', true);

                    if (this.isCreatingAbility) {
                        this.abilities.push(response);
                        this.abilities.sort((a, b) => a.name.localeCompare(b.name));
                    } else {
                        // Replace ability in list with updated info
                        const index = this.abilities.findIndex((ability) => ability.ability_id === this.selectedAbility.ability_id);
                        this.abilities[index] = response;
                    }
                    this.filterAbilities();
                }).catch((error) => {
                    toast('Error saving ability', false);
                    console.error(error);
                });
            },

            deleteAbility() {
                if (confirm('Are you sure you want to delete this ability?')) {
                    apiV2('DELETE', `/api/v2/abilities/${this.selectedAbility.ability_id}`).then((response) => {
                        toast('Removed ability', true);
                        this.showAbilityModal = false;
                        this.abilities.splice(this.abilities.findIndex((ability) => this.selectedAbility.ability_id === ability.ability_id), 1);
                        this.filterAbilities();
                    }).catch((error) => {
                        toast('Could not delete ability', false);
                        console.error(error);
                    });
                }
            },

            addExecutorToAbility(bOrA) {
                const template = {
                    payloads: [],
                    platform: 'linux',
                    name: 'sh',
                    cleanup: [],
                    parsers: []
                };

                if (bOrA === 'after') {
                    this.selectedAbility.executors.push(template);
                } else if (bOrA === 'before') {
                    this.selectedAbility.executors.unshift(template);
                }
            },

            filterUndefined(data){
                for (let i = 0; i < data.requirements.length; i++){
                    if (data.requirements[i].module === undefined || data.requirements[i].module === ""){
                        data.requirements.splice(i, 1);
                    }
                    else if (data.requirements[i]['relationship_match'][0].source === undefined ||
                        data.requirements[i]['relationship_match'][0].source === ""
                    ){
                        data.requirements.splice(i, 1);
                    }
                    else if (data.requirements[i]['relationship_match'][0].edge === undefined ||
                        data.requirements[i]['relationship_match'][0].edge === ""
                    ) {
                        delete data.requirements[i]['relationship_match'][0].edge;
                        delete data.requirements[i]['relationship_match'][0].target;
                    }
                    else if (data.requirements[i]['relationship_match'][0].target === undefined ||
                        data.requirements[i]['relationship_match'][0].target === ""
                    ) {
                        delete data.requirements[i]['relationship_match'][0].target;
                    }
                }

                for (let i = 0; i < data.executors.length; i++){
                    for (let j = 0; j < data.executors[i].parsers.length; j++){
                        if (data.executors[i].parsers[j].module === undefined ||
                            data.executors[i].parsers[j].module === ""){
                            data.executors[i].parsers.splice(j, 1);
                        }
                        else if (data.executors[i].parsers[j]["parserconfigs"][0].source === undefined ||
                            data.executors[i].parsers[j]["parserconfigs"][0].source === ""
                        ) {
                            data.executors[i].parsers.splice(j, 1);
                        }
                        else if (data.executors[i].parsers[j]["parserconfigs"][0].edge === undefined ||
                            data.executors[i].parsers[j]["parserconfigs"][0].edge === ""
                        ) {
                            delete data.executors[i].parsers[j]['parserconfigs'][0].edge;
                            delete data.executors[i].parsers[j]['parserconfigs'][0].target;
                        }
                        else if (data.executors[i].parsers[j]["parserconfigs"][0].target === undefined ||
                            data.executors[i].parsers[j]["parserconfigs"][0].target === ""
                        ) {
                            delete data.executors[i].parsers[j]['parserconfigs'][0].target;
                        }
                    }
                }
                return data;
            }
        };
    }

    // # sourceURL=abilities.js
</script>

<style scoped>
    .platforms {
        position: absolute;
        top: 10px;
        right: 15px;
    }

    .filters {
        border-right: 1px solid rgb(97, 97, 97);
    }

    @media(max-width: 1200px) {
        .box.ability {
            width: 98%;
        }
    }
    @media(min-width: 1200px) {
        .box.ability {
            width: 48%;
        }
    }
    .box.ability {
        position: relative;
        cursor: pointer;
        border: 1px solid transparent;
        background-color: #272727;
    }
    .box.ability:hover {
        border: 1px solid #474747;
    }

    .abilities {
        overflow-x: hidden;
    }

    .ability-detail.modal-card-body {
        overflow-x: hidden;
    }

    .has-tooltip-arrow.no-underline {
        border-bottom: none;
    }

    .tag.tactic {
        background-color: #1a1a1a;
    }
</style>
