// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.settings.website;

import androidx.annotation.Nullable;

import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.ContentSettingsType;
import org.chromium.chrome.browser.settings.website.WebsitePreferenceBridge.StorageInfoClearedCallback;
import org.chromium.chrome.browser.util.MathUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Website is a class for storing information about a website and its associated permissions.
 */
public class Website implements Serializable {
    static final int INVALID_CAMERA_OR_MICROPHONE_ACCESS = 0;
    static final int CAMERA_ACCESS_ALLOWED = 1;
    static final int MICROPHONE_AND_CAMERA_ACCESS_ALLOWED = 2;
    static final int MICROPHONE_ACCESS_ALLOWED = 3;
    static final int CAMERA_ACCESS_DENIED = 4;
    static final int MICROPHONE_AND_CAMERA_ACCESS_DENIED = 5;
    static final int MICROPHONE_ACCESS_DENIED = 6;

    private final WebsiteAddress mOrigin;
    private final WebsiteAddress mEmbedder;

    /**
     * Indexed by ContentSettingException.Type.
     */
    private ContentSettingException mContentSettingException[];
    /**
     * Indexed by PermissionInfo.Type.
     */
    private PermissionInfo[] mPermissionInfo;

    private LocalStorageInfo mLocalStorageInfo;
    private final List<StorageInfo> mStorageInfo = new ArrayList<StorageInfo>();
    private int mStorageInfoCallbacksLeft;

    // The collection of chooser-based permissions (e.g. USB device access) granted to this site.
    // Each entry declares its own ContentSettingsType and so depending on how this object was
    // built this list could contain multiple types of objects.
    private final List<ChosenObjectInfo> mObjectInfo = new ArrayList<ChosenObjectInfo>();

    public Website(WebsiteAddress origin, WebsiteAddress embedder) {
        mOrigin = origin;
        mEmbedder = embedder;
        mPermissionInfo = new PermissionInfo[PermissionInfo.Type.NUM_ENTRIES];
        mContentSettingException =
                new ContentSettingException[ContentSettingException.Type.NUM_ENTRIES];
    }

    public WebsiteAddress getAddress() {
        return mOrigin;
    }

    public String getTitle() {
        return mOrigin.getTitle();
    }

    public String getSummary() {
        if (mEmbedder == null) return null;
        return mEmbedder.getTitle();
    }

    /**
     * A comparison function for sorting by address (first by origin and then
     * by embedder).
     */
    public int compareByAddressTo(Website to) {
        if (this == to) return 0;
        int originComparison = mOrigin.compareTo(to.mOrigin);
        if (originComparison == 0) {
            if (mEmbedder == null) return to.mEmbedder == null ? 0 : -1;
            if (to.mEmbedder == null) return 1;
            return mEmbedder.compareTo(to.mEmbedder);
        }
        return originComparison;
    }

    /**
     * A comparison function for sorting by storage (most used first).
     * @return which site uses more storage.
     */
    public int compareByStorageTo(Website to) {
        if (this == to) return 0;
        return MathUtils.compareLongs(to.getTotalUsage(), getTotalUsage());
    }

    /**
     * @return PermissionInfo with permission details of specified type
     *         (Camera, Clipboard, etc.).
     */
    public PermissionInfo getPermissionInfo(@PermissionInfo.Type int type) {
        return mPermissionInfo[type];
    }

    /**
     * Set PermissionInfo for permission details of specified type
     * (Camera, Clipboard, etc.).
     */
    public void setPermissionInfo(PermissionInfo info) {
        mPermissionInfo[info.getType()] = info;
    }

    /**
     * @return permission value for permission of specified type.
     *         (Camera, Clipboard, etc.).
     */
    public @ContentSettingValues @Nullable Integer getPermission(@PermissionInfo.Type int type) {
        return getPermissionInfo(type) != null ? getPermissionInfo(type).getContentSetting() : null;
    }

    /**
     * Set permission value for permission of specified type
     * (Camera, Clipboard, etc.).
     */
    public void setPermission(@PermissionInfo.Type int type, @ContentSettingValues int value) {
        if (getPermissionInfo(type) != null) getPermissionInfo(type).setContentSetting(value);
    }

    /**
     * Returns the exception info for this Website for specified type.
     */
    public ContentSettingException getContentSettingException(
            @ContentSettingException.Type int type) {
        return mContentSettingException[type];
    }

    /**
     * Sets the exception info for this Website for specified type.
     */
    public void setContentSettingException(
            @ContentSettingException.Type int type, ContentSettingException exception) {
        mContentSettingException[type] = exception;
    }

    /**
     * Returns what ContentSettingException governs the setting of specified type.
     */
    public @ContentSettingValues @Nullable Integer getContentSettingPermission(
            @ContentSettingException.Type int type) {
        return mContentSettingException[type] != null
                ? mContentSettingException[type].getContentSetting()
                : null;
    }

    /**
     * Sets the permission.
     */
    public void setContentSettingPermission(
            @ContentSettingException.Type int type, @ContentSettingValues int value) {
        if (type == ContentSettingException.Type.ADS) {
            // It is possible to set the permission without having an existing exception,
            // because we can show the BLOCK state even when this permission is set to the
            // default. In that case, just set an exception now to BLOCK to enable changing the
            // permission.
            if (mContentSettingException[type] == null) {
                mContentSettingException[type] =
                        new ContentSettingException(ContentSettingsType.ADS,
                                getAddress().getOrigin(), ContentSettingValues.BLOCK, "");
            }
        } else if (type == ContentSettingException.Type.SOUND) {
            // It is possible to set the permission without having an existing exception,
            // because we always show the sound permission in Site Settings.
            if (mContentSettingException[type] == null) {
                mContentSettingException[type] = new ContentSettingException(
                        ContentSettingsType.SOUND, getAddress().getHost(), value, "");
            }
            if (value == ContentSettingValues.BLOCK) {
                RecordUserAction.record("SoundContentSetting.MuteBy.SiteSettings");
            } else {
                RecordUserAction.record("SoundContentSetting.UnmuteBy.SiteSettings");
            }
            // We want setContentSetting to be called even after calling setSoundException
            // above because this will trigger the actual change on the PrefServiceBridge.
        }
        if (mContentSettingException[type] != null) {
            mContentSettingException[type].setContentSetting(value);
        }
    }

    public void setLocalStorageInfo(LocalStorageInfo info) {
        mLocalStorageInfo = info;
    }

    public LocalStorageInfo getLocalStorageInfo() {
        return mLocalStorageInfo;
    }

    public void addStorageInfo(StorageInfo info) {
        mStorageInfo.add(info);
    }

    public List<StorageInfo> getStorageInfo() {
        return new ArrayList<StorageInfo>(mStorageInfo);
    }

    public void clearAllStoredData(final StoredDataClearedCallback callback) {
        // Wait for callbacks from each mStorageInfo and another callback from
        // mLocalStorageInfo.
        mStorageInfoCallbacksLeft = mStorageInfo.size() + 1;
        StorageInfoClearedCallback clearedCallback = () -> {
            if (--mStorageInfoCallbacksLeft == 0) callback.onStoredDataCleared();
        };
        if (mLocalStorageInfo != null) {
            mLocalStorageInfo.clear(clearedCallback);
            mLocalStorageInfo = null;
        } else {
            clearedCallback.onStorageInfoCleared();
        }
        for (StorageInfo info : mStorageInfo) info.clear(clearedCallback);
        mStorageInfo.clear();
    }

    /**
     * An interface to implement to get a callback when storage info has been cleared.
     */
    public interface StoredDataClearedCallback { public void onStoredDataCleared(); }

    public long getTotalUsage() {
        long usage = 0;
        if (mLocalStorageInfo != null) usage += mLocalStorageInfo.getSize();
        for (StorageInfo info : mStorageInfo) usage += info.getSize();
        return usage;
    }

    /**
     * Add information about an object the user has granted permission for this site to access.
     */
    public void addChosenObjectInfo(ChosenObjectInfo info) {
        mObjectInfo.add(info);
    }

    /**
     * Returns the set of objects this website has been granted permission to access.
     */
    public List<ChosenObjectInfo> getChosenObjectInfo() {
        return new ArrayList<ChosenObjectInfo>(mObjectInfo);
    }
}
