// Copyright (C) 2019 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 com.googlesource.gerrit.plugins.websession.broker;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.gerritforge.gerrit.eventbroker.BrokerApi;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.httpd.FakeWebSessionVal;
import com.google.gerrit.httpd.WebSessionManager.Val;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.events.Event;
import com.googlesource.gerrit.plugins.websession.broker.BrokerBasedWebSessionCache.WebSessionEvent;
import com.googlesource.gerrit.plugins.websession.broker.BrokerBasedWebSessionCache.WebSessionEvent.Operation;
import com.googlesource.gerrit.plugins.websession.broker.log.WebSessionLogger;
import com.googlesource.gerrit.plugins.websession.broker.util.TimeMachine;
import java.time.Instant;
import java.util.concurrent.ExecutorService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class BrokerBasedWebSessionCacheTest {

  private static final int DEFAULT_ACCOUNT_ID = 1000000;
  private static final String KEY = "aSceprtma6B0qZ0hKxXHvQ5iyfUhCcFXxG";
  private static Val VAL = FakeWebSessionVal.getVal(Account.id(1), ExternalId.Key.parse("foo:bar"));
  private static final String PLUGIN_NAME = "websession-broker";

  private byte[] emptyPayload = new byte[] {-84, -19, 0, 5, 112};
  byte[] defaultPayload =
      new byte[] {
        -84, -19, 0, 5, 115, 114, 0, 45, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, 46, 103,
        101, 114, 114, 105, 116, 46, 104, 116, 116, 112, 100, 46, 87, 101, 98, 83, 101, 115, 115,
        105, 111, 110, 77, 97, 110, 97, 103, 101, 114, 36, 86, 97, 108, 0, 0, 0, 0, 0, 0, 0, 2, 3,
        0, 0, 120, 112, 119, 97, 1, -64, -124, 61, 2, 0, 0, 1, 111, 13, -8, 90, 7, 3, 0, 5, 34, 97,
        83, 99, 101, 112, 114, 113, 86, 87, 54, 85, 79, 45, 88, 51, 107, 51, 116, 102, 85, 109, 86,
        103, 82, 73, 90, 56, 53, 99, 99, 52, 71, 114, 87, 6, 0, 0, 1, 111, 16, 84, -103, -121, 7,
        34, 97, 83, 99, 101, 112, 114, 114, 82, 103, 119, 49, 71, 110, 90, 56, 122, 54, 49, 49, 86,
        52, 121, 110, 65, 100, 110, 113, 99, 68, 45, 105, 99, 75, 97, 0, 120
      };

  ExecutorService executorServce = MoreExecutors.newDirectExecutorService();

  @Mock BrokerApi brokerApi;
  Cache<String, Val> cache;
  @Mock TimeMachine timeMachine;
  @Mock PluginConfigFactory cfg;
  @Mock PluginConfig pluginConfig;
  @Mock WebSessionLogger webSessionLogger;
  @Captor ArgumentCaptor<Event> eventCaptor;
  @Captor ArgumentCaptor<Val> valCaptor;

  BrokerBasedWebSessionCache objectUnderTest;

  String instanceId = "instance-id";

  @Before
  public void setup() {
    cache = CacheBuilder.newBuilder().build();
    when(pluginConfig.getString("webSessionTopic", "gerrit_web_session"))
        .thenReturn("gerrit_web_session");
    when(cfg.getFromGerritConfig(PLUGIN_NAME)).thenReturn(pluginConfig);
    when(timeMachine.now()).thenReturn(Instant.EPOCH);
    DynamicItem<BrokerApi> item = DynamicItem.itemOf(BrokerApi.class, brokerApi);
    objectUnderTest =
        new BrokerBasedWebSessionCache(
            cache,
            item,
            timeMachine,
            cfg,
            PLUGIN_NAME,
            webSessionLogger,
            executorServce,
            instanceId);
  }

  @Test
  public void shouldPublishMessageWhenLoginEvent() {
    WebSessionEvent eventMessage = createEventMessage();
    Val value = createVal(eventMessage);

    objectUnderTest.put(KEY, value);
    verify(brokerApi, times(1)).send(anyString(), eventCaptor.capture());

    assertThat(eventCaptor.getValue()).isNotNull();
    WebSessionEvent event = (WebSessionEvent) eventCaptor.getValue();
    assertThat(event.operation).isEqualTo(WebSessionEvent.Operation.ADD);
    assertThat(event.key).isEqualTo(KEY);
    assertThat(event.payload).isEqualTo(defaultPayload);
  }

  @Test
  public void shouldPublishMessageWhenLogoutEvent() {
    objectUnderTest.invalidate(KEY);

    verify(brokerApi, times(1)).send(anyString(), eventCaptor.capture());

    assertThat(eventCaptor.getValue()).isNotNull();
    WebSessionEvent event = (WebSessionEvent) eventCaptor.getValue();
    assertThat(event.operation).isEqualTo(WebSessionEvent.Operation.REMOVE);
    assertThat(event.key).isEqualTo(KEY);
    assertThat(event.payload).isEqualTo(emptyPayload);
  }

  @Test
  public void shouldUpdateCacheWhenLoginMessageReceived() {
    WebSessionEvent eventMessage = createEventMessage();

    objectUnderTest.processMessage(eventMessage);

    Val val = cache.getIfPresent(eventMessageKey(eventMessage));
    assertThat(val).isNotNull();
    assertThat(val.getAccountId().get()).isEqualTo(DEFAULT_ACCOUNT_ID);
  }

  @Test
  public void shouldUpdateCacheWhenLogoutMessageReceived() {
    WebSessionEvent eventMessage = createEventMessage(emptyPayload, Operation.REMOVE);
    cache.put(KEY, VAL);

    objectUnderTest.processMessage(eventMessage);

    assertThat(cache.getIfPresent(KEY)).isNull();
  }

  @Test
  public void shouldCleanupExpiredSessions() {
    when(timeMachine.now()).thenReturn(Instant.MIN, Instant.MAX);

    WebSessionEvent eventMessage = createEventMessage();

    objectUnderTest.processMessage(eventMessage);

    Val val = cache.getIfPresent(eventMessageKey(eventMessage));
    assertThat(val).isNotNull();

    objectUnderTest.cleanUp();

    assertThat(cache.getIfPresent(eventMessageKey(eventMessage))).isNull();
  }

  private Val createVal(Event message) {
    WebSessionEvent event = (WebSessionEvent) message;

    objectUnderTest.processMessage(message);
    return cache.getIfPresent(event.key);
  }

  private WebSessionEvent createEventMessage() {

    return createEventMessage(defaultPayload, Operation.ADD);
  }

  private String eventMessageKey(WebSessionEvent eventMessage) {
    return eventMessage.key;
  }

  private WebSessionEvent createEventMessage(byte[] payload, Operation operation) {
    WebSessionEvent event = new WebSessionEvent(KEY, payload, operation);
    event.instanceId = instanceId;
    return event;
  }
}
