/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view.textclassifier;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.text.Spannable;
import android.text.style.ClickableSpan;
import android.text.util.Linkify;
import android.text.util.Linkify.LinkifyMask;
import android.view.textclassifier.TextLinks.TextLink;
import android.view.textclassifier.TextLinks.TextLinkSpan;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

/**
 * Parameters for generating and applying links.
 * @hide
 */
public final class TextLinksParams {

    /**
     * A function to create spans from TextLinks.
     */
    private static final Function<TextLink, TextLinkSpan> DEFAULT_SPAN_FACTORY =
            textLink -> new TextLinkSpan(textLink);

    @TextLinks.ApplyStrategy
    private final int mApplyStrategy;
    private final Function<TextLink, TextLinkSpan> mSpanFactory;
    private final TextClassifier.EntityConfig mEntityConfig;

    private TextLinksParams(
            @TextLinks.ApplyStrategy int applyStrategy,
            Function<TextLink, TextLinkSpan> spanFactory) {
        mApplyStrategy = applyStrategy;
        mSpanFactory = spanFactory;
        mEntityConfig = TextClassifier.EntityConfig.createWithHints(null);
    }

    /**
     * Returns a new TextLinksParams object based on the specified link mask.
     *
     * @param mask the link mask
     *      e.g. {@link LinkifyMask#PHONE_NUMBERS} | {@link LinkifyMask#EMAIL_ADDRESSES}
     * @hide
     */
    @NonNull
    public static TextLinksParams fromLinkMask(@LinkifyMask int mask) {
        final List<String> entitiesToFind = new ArrayList<>();
        if ((mask & Linkify.WEB_URLS) != 0) {
            entitiesToFind.add(TextClassifier.TYPE_URL);
        }
        if ((mask & Linkify.EMAIL_ADDRESSES) != 0) {
            entitiesToFind.add(TextClassifier.TYPE_EMAIL);
        }
        if ((mask & Linkify.PHONE_NUMBERS) != 0) {
            entitiesToFind.add(TextClassifier.TYPE_PHONE);
        }
        if ((mask & Linkify.MAP_ADDRESSES) != 0) {
            entitiesToFind.add(TextClassifier.TYPE_ADDRESS);
        }
        return new TextLinksParams.Builder().setEntityConfig(
                TextClassifier.EntityConfig.createWithExplicitEntityList(entitiesToFind))
                .build();
    }

    /**
     * Returns the entity config used to determine what entity types to generate.
     */
    @NonNull
    public TextClassifier.EntityConfig getEntityConfig() {
        return mEntityConfig;
    }

    /**
     * Annotates the given text with the generated links. It will fail if the provided text doesn't
     * match the original text used to crete the TextLinks.
     *
     * @param text the text to apply the links to. Must match the original text
     * @param textLinks the links to apply to the text
     *
     * @return a status code indicating whether or not the links were successfully applied
     * @hide
     */
    @TextLinks.Status
    public int apply(@NonNull Spannable text, @NonNull TextLinks textLinks) {
        Objects.requireNonNull(text);
        Objects.requireNonNull(textLinks);

        final String textString = text.toString();

        if (Linkify.containsUnsupportedCharacters(textString)) {
            // Do not apply links to text containing unsupported characters.
            android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
            return TextLinks.STATUS_UNSUPPORTED_CHARACTER;
        }

        if (!textString.startsWith(textLinks.getText())) {
            return TextLinks.STATUS_DIFFERENT_TEXT;
        }
        if (textLinks.getLinks().isEmpty()) {
            return TextLinks.STATUS_NO_LINKS_FOUND;
        }

        int applyCount = 0;
        for (TextLink link : textLinks.getLinks()) {
            final TextLinkSpan span = mSpanFactory.apply(link);
            if (span != null) {
                final ClickableSpan[] existingSpans = text.getSpans(
                        link.getStart(), link.getEnd(), ClickableSpan.class);
                if (existingSpans.length > 0) {
                    if (mApplyStrategy == TextLinks.APPLY_STRATEGY_REPLACE) {
                        for (ClickableSpan existingSpan : existingSpans) {
                            text.removeSpan(existingSpan);
                        }
                        text.setSpan(span, link.getStart(), link.getEnd(),
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                        applyCount++;
                    }
                } else {
                    text.setSpan(span, link.getStart(), link.getEnd(),
                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    applyCount++;
                }
            }
        }
        if (applyCount == 0) {
            return TextLinks.STATUS_NO_LINKS_APPLIED;
        }
        return TextLinks.STATUS_LINKS_APPLIED;
    }

    /**
     * A builder for building TextLinksParams.
     */
    public static final class Builder {

        @TextLinks.ApplyStrategy
        private int mApplyStrategy = TextLinks.APPLY_STRATEGY_IGNORE;
        private Function<TextLink, TextLinkSpan> mSpanFactory = DEFAULT_SPAN_FACTORY;

        /**
         * Sets the apply strategy used to determine how to apply links to text.
         *      e.g {@link TextLinks#APPLY_STRATEGY_IGNORE}
         *
         * @return this builder
         */
        public Builder setApplyStrategy(@TextLinks.ApplyStrategy int applyStrategy) {
            mApplyStrategy = checkApplyStrategy(applyStrategy);
            return this;
        }

        /**
         * Sets a custom span factory for converting TextLinks to TextLinkSpans.
         * Set to {@code null} to use the default span factory.
         *
         * @return this builder
         */
        public Builder setSpanFactory(@Nullable Function<TextLink, TextLinkSpan> spanFactory) {
            mSpanFactory = spanFactory == null ? DEFAULT_SPAN_FACTORY : spanFactory;
            return this;
        }

        /**
         * Sets the entity configuration used to determine what entity types to generate.
         * Set to {@code null} for the default entity config which will automatically determine
         * what links to generate.
         *
         * @return this builder
         */
        public Builder setEntityConfig(@Nullable TextClassifier.EntityConfig entityConfig) {
            return this;
        }

        /**
         * Builds and returns a TextLinksParams object.
         */
        public TextLinksParams build() {
            return new TextLinksParams(mApplyStrategy, mSpanFactory);
        }
    }

    /** @throws IllegalArgumentException if the value is invalid */
    @TextLinks.ApplyStrategy
    private static int checkApplyStrategy(int applyStrategy) {
        if (applyStrategy != TextLinks.APPLY_STRATEGY_IGNORE
                && applyStrategy != TextLinks.APPLY_STRATEGY_REPLACE) {
            throw new IllegalArgumentException(
                    "Invalid apply strategy. See TextLinksParams.ApplyStrategy for options.");
        }
        return applyStrategy;
    }
}

