package ch.threema.domain.protocol;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import androidx.annotation.LongDef;
import ch.threema.protobuf.common.CspFeatureMaskFlag;

public class ThreemaFeature {
    public final static long AUDIO = CspFeatureMaskFlag.VOICE_MESSAGE_SUPPORT_VALUE;
    public final static long GROUP_CHAT = CspFeatureMaskFlag.GROUP_SUPPORT_VALUE;
    public final static long POLL = CspFeatureMaskFlag.POLL_SUPPORT_VALUE;
    public final static long FILE = CspFeatureMaskFlag.FILE_MESSAGE_SUPPORT_VALUE;
    public final static long VOIP = CspFeatureMaskFlag.O2O_AUDIO_CALL_SUPPORT_VALUE;
    public final static long VIDEOCALLS = CspFeatureMaskFlag.O2O_VIDEO_CALL_SUPPORT_VALUE;
    public final static long FORWARD_SECURITY = CspFeatureMaskFlag.FORWARD_SECURITY_SUPPORT_VALUE;
    public final static long GROUP_CALLS = CspFeatureMaskFlag.GROUP_CALL_SUPPORT_VALUE;
    public final static long EDIT_MESSAGES = CspFeatureMaskFlag.EDIT_MESSAGE_SUPPORT_VALUE;
    public final static long DELETE_MESSAGES = CspFeatureMaskFlag.DELETE_MESSAGE_SUPPORT_VALUE;
    public final static long EMOJI_REACTIONS = CspFeatureMaskFlag.REACTION_SUPPORT_VALUE;

    @Retention(RetentionPolicy.SOURCE)
    @LongDef({AUDIO, GROUP_CHAT, POLL, FILE, VOIP, VIDEOCALLS, FORWARD_SECURITY, GROUP_CALLS, EDIT_MESSAGES, DELETE_MESSAGES, EMOJI_REACTIONS})
    public @interface Feature {
    }

    /**
     * Feature mask builder
     */
    public static class Builder {
        private long mask = 0;

        public Builder audio(boolean enable) {
            return this.set(ThreemaFeature.AUDIO, enable);
        }

        public Builder group(boolean enable) {
            return this.set(ThreemaFeature.GROUP_CHAT, enable);
        }

        public Builder poll(boolean enable) {
            return this.set(ThreemaFeature.POLL, enable);
        }

        public Builder file(boolean enable) {
            return this.set(ThreemaFeature.FILE, enable);
        }

        public Builder voip(boolean enable) {
            return this.set(ThreemaFeature.VOIP, enable);
        }

        public Builder videocalls(boolean enable) {
            return this.set(ThreemaFeature.VIDEOCALLS, enable);
        }

        public Builder forwardSecurity(boolean enable) {
            return this.set(ThreemaFeature.FORWARD_SECURITY, enable);
        }

        public Builder groupCalls(boolean enable) {
            return this.set(ThreemaFeature.GROUP_CALLS, enable);
        }

        public Builder editMessages(boolean enable) {
            return this.set(ThreemaFeature.EDIT_MESSAGES, enable);
        }

        public Builder deleteMessages(boolean enable) {
            return this.set(ThreemaFeature.DELETE_MESSAGES, enable);
        }

        public Builder emojiReactions(boolean enable) {
            return this.set(ThreemaFeature.EMOJI_REACTIONS, enable);
        }

        public long build() {
            return this.mask;
        }

        private Builder set(@Feature long feature, boolean enable) {
            if (enable) {
                this.mask |= feature;
            } else {
                this.mask &= ~feature;
            }
            return this;
        }
    }

    public static boolean canText(long featureMask) {
        return true;
    }

    public static boolean canImage(long featureMask) {
        return true;
    }

    public static boolean canVideo(long featureMask) {
        return true;
    }

    public static boolean canAudio(long featureMask) {
        return hasFeature(featureMask, AUDIO);
    }

    public static boolean canGroupChat(long featureMask) {
        return hasFeature(featureMask, GROUP_CHAT);
    }

    public static boolean canPoll(long featureMask) {
        return hasFeature(featureMask, POLL);
    }

    public static boolean canFile(long featureMask) {
        return hasFeature(featureMask, FILE);
    }

    public static boolean canVoip(long featureMask) {
        return hasFeature(featureMask, VOIP);
    }

    public static boolean canVideocall(long featureMask) {
        return hasFeature(featureMask, VIDEOCALLS);
    }

    public static boolean canForwardSecurity(long featureMask) {
        return hasFeature(featureMask, FORWARD_SECURITY);
    }

    public static boolean canGroupCalls(long featureMask) {
        return hasFeature(featureMask, GROUP_CALLS);
    }

    public static boolean canEditMessages(long featureMask) {
        return hasFeature(featureMask, EDIT_MESSAGES);
    }

    public static boolean canDeleteMessages(long featureMask) {
        return hasFeature(featureMask, DELETE_MESSAGES);
    }

    public static boolean canEmojiReactions(long featureMask) {
        return hasFeature(featureMask, EMOJI_REACTIONS);
    }

    public static boolean hasFeature(long featureMask, @Feature long feature) {
        return (featureMask & feature) != 0;
    }

    /**
     * Convert a feature mask to a classic feature level.
     */
    // TODO(ANDR-2708): Remove
    public static long featureMaskToLevel(long featureMask) {
        if ((featureMask & FILE) > 0) {
            return 3;
        }
        if ((featureMask & POLL) > 0) {
            return 2;
        }
        if ((featureMask & GROUP_CHAT) > 0) {
            return 1;
        }
        return 0;
    }
}
