// 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.any;
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.gerritforge.gerrit.eventbroker.EventMessage;
import com.gerritforge.gerrit.eventbroker.EventMessage.Header;
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.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.UUID;
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 =
      new Val(Account.id(1), 0, false, ExternalId.Key.parse("foo:bar"), 0, "", "");
  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<EventMessage> eventCaptor;
  @Captor ArgumentCaptor<Val> valCaptor;

  BrokerBasedWebSessionCache objectUnderTest;

  @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);
  }

  @Test
  public void shouldPublishMessageWhenLoginEvent() {
    EventMessage eventMessage = createEventMessage();
    Val value = createVal(eventMessage);
    when(brokerApi.newMessage(any(UUID.class), any(Event.class))).thenReturn(eventMessage);

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

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

  @Test
  public void shouldPublishMessageWhenLogoutEvent() {
    EventMessage eventMessage = createEventMessage(emptyPayload, Operation.REMOVE);
    when(brokerApi.newMessage(any(UUID.class), any(Event.class))).thenReturn(eventMessage);

    objectUnderTest.invalidate(KEY);

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

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

  @Test
  public void shouldUpdateCacheWhenLoginMessageReceived() {
    EventMessage 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() {
    EventMessage 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);

    EventMessage 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(EventMessage message) {
    WebSessionEvent event = (WebSessionEvent) message.getEvent();

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

  private EventMessage createEventMessage() {

    return createEventMessage(defaultPayload, Operation.ADD);
  }

  private String eventMessageKey(EventMessage eventMessage) {
    WebSessionEvent sessionEvent = (WebSessionEvent) eventMessage.getEvent();
    return sessionEvent.key;
  }

  private EventMessage createEventMessage(byte[] payload, Operation operation) {

    Header header =
        new Header(
            UUID.fromString("7cb80dbe-65c4-4f2c-84de-580d98199d4a"),
            UUID.fromString("97711495-1013-414e-bfd2-44776787520d"));
    WebSessionEvent event = new WebSessionEvent(KEY, payload, operation);
    return new EventMessage(header, event);
  }
}
