import { Injectable } from "@angular/core";
import Gun from "gun/gun";
import "gun/lib/then";

@Injectable()
export class P2pDatabaseGunProvider {
  private gun;
  osnPrefix: string = "hybridOSN-beta011";

  constructor() {
    this.gun = Gun(["https://hybrid-osn.herokuapp.com/gun"]);
  }

  /**
   * Hashtags are stored without reference to the users to provide these information on an extra dashboard to twitter
   * @param hashtagEntity extracted hashtags
   */
  public async publishHashtags(hashtagEntity): Promise<void> {
    const timestamp = new Date().setHours(0, 0, 1, 0);
    const hashtagsSeparated = hashtagEntity
      .map(el => el.hashtag)
      .sort()
      .join("|");

    const randomId = Math.floor(Math.random() * 10000000000);

    const hashtags = this.gun
      .get(randomId)
      .put({ hashtags: hashtagsSeparated });

    this.gun
      .get(this.osnPrefix)
      .get("hashtags")
      .get(timestamp)
      .set(hashtags);
  }

  public storeLastTweetHashForUser(userId, hash, timestamp): void {
    const tweet = this.gun
      .get(timestamp)
      .put({ hash: hash, created_at: timestamp });

    this.gun
      .get(this.osnPrefix)
      .get("tweets")
      .get(userId)
      .set(tweet);
  }

  public async fetchPrivateTweetHashsForUserInInterval(
    userId,
    intervalStart,
    intervalEnd
  ): Promise<object[]> {
    const privateTweets = await this.gun
      .get(this.osnPrefix)
      .get("tweets")
      .get(userId)
      .then();

    if (privateTweets) {
      const entries = await Promise.all(
        Object.keys(privateTweets)
          .filter(key => key !== "_")
          .map(key => this.gun.get(key).then())
      );

      return entries
        .filter(entry => {
          const createdAtDate = new Date(entry["created_at"]);
          return createdAtDate < intervalStart && createdAtDate >= intervalEnd;
        })
        .map(entry => {
          entry.userId = userId;
          return entry;
        });
    } else {
      return [];
    }
  }

  public async addLike(tweetId: string) {
    const likeEntry = await this.getLikes(tweetId);

    const likes = this.gun.get(tweetId).put({
      likes: likeEntry.likes + 1
    });

    this.gun
      .get(this.osnPrefix)
      .get("likes")
      .set(likes);
  }

  public async getLikes(tweetId: string) {
    const likeEntry = await this.gun
      .get(this.osnPrefix)
      .get("likes")
      .get(tweetId)
      .then();

    if (likeEntry === undefined) {
      return {
        likes: 0
      };
    } else {
      return likeEntry;
    }
  }
}
