#!/usr/bin/env python3
from bs4 import BeautifulSoup
from enum import IntEnum
from nullroute.sec import get_netrc
from nullroute.core import Core
from nullroute.scrape import Scraper
import os
from pprint import pprint
import sys
import subprocess

class DbIndex(IntEnum):
    Pixiv = 5
    Seiga = 8
    DeviantArt = 34

class SauceNao(Scraper):
    upload_uri = "https://saucenao.com/search.php"

    boards = [
        "yandere",
        "danbooru",
        "konachan",
        "gelbooru",
        "sankaku",
        "anime-pictures",
        "e621",
    ]

    fmt = {
        "pixiv_illust": "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=%s",
        "pixiv_member": "http://www.pixiv.net/member_illust.php?id=%s",

        "seiga_illust": "http://seiga.nicovideo.jp/seiga/im%s",
        "seiga_member": "http://seiga.nicovideo.jp/user/illust/%s",

        "da_illust":    "https://deviantart.com/view/%s",

        "anime-pictures_id": "https://anime-pictures.net/pictures/view_post/%s",
        "danbooru_id":  "https://danbooru.donmai.us/posts/%s",
        "danbooru_tag": "https://danbooru.donmai.us/posts?tags=%s",
        "e621_id":      "https://e621.net/post/show/%s",
        "gelbooru_id":  "https://gelbooru.com/index.php?page=post&s=view&id=%s",
        "konachan_id":  "http://konachan.com/post/show/%s",
        "sankaku_id":   "https://chan.sankakucomplex.com/post/show/%s",
        "yandere_id":   "https://yande.re/post/show/%s",
    }

    def __init__(self, api_key=""):
        self.api_key = api_key
        super().__init__()

    def trash(self, file):
        r = subprocess.call(["mkdir", "-p", "_trash"]) == 0
        if r:
            r = subprocess.call(["mv", file, "_trash/"]) == 0
        return r

    def swap(self, old_file, new_url, kind):
        return False

        if kind == "pixiv":
            r = subprocess.call(["pixiv-dl", new_url]) == 0
            if r:
                r = self.trash(old_file)
            return r
        elif kind in {"danbooru", "gelbooru", "konachan", "sankaku", "yandere"}:
            r = subprocess.call(["fix-gelbooru-names", "--site=%s" % kind, new_url]) == 0
            if r:
                r = self.trash(old_file)
            return r
        else:
            return False

    def _format_data(self, data, consumed):
        if "pixiv_id" in data:
            yield ("Pixiv ID", data["pixiv_id"], self.fmt["pixiv_illust"] % data["pixiv_id"])
            yield ("Member", data["member_name"], self.fmt["pixiv_member"] % data["member_id"])
            consumed |= {"pixiv_id", "member_name", "member_id"}

    def find(self, file):
        Core.info("uploading %r" % file)
        resp = self.ua.post(self.upload_uri,
                            params={
                                "api_key": self.api_key,
                                "output_type": "2",
                            },
                            files={
                                "file": (os.path.basename(file), open(file, "rb")),
                                "frame": "1",
                                "database": "999",
                            })
        resp.raise_for_status()
        data = resp.json()
        Core.info("remaining queries: %(short_remaining)s/%(short_limit)s (fast)," \
                  " %(long_remaining)s/%(long_limit)s (daily)" % data["header"])
        swapped = False
        if not data["results"]:
            Core.err("no results for image")
            return

        for res in data["results"]:
            head = res["header"]
            index = int(head["index_id"])
            score = float(head["similarity"])
            data = res["data"]

            if score < 80:
                Core.debug("skipping %r with low score" % res)
                continue

            print(" * %(index_name)s" % head)
            print("   Score:", head["similarity"])

            fmt = "   %s:"
            consumed = set()
            seenurls = set()

            if data.get("title"):
                print(fmt % "Title", data["title"])
                consumed |= {"title"}

            for head, name, url in self._format_data(data, consumed):
                if head in {"Member"}:
                    name = "｢%s｣" % name
                print(fmt % head, name, "<%s>" % url)

            if index == DbIndex.Pixiv:
                if score >= 92 and not swapped:
                    swapped = self.swap(file, self.fmt["pixiv_illust"] % data["pixiv_id"], "pixiv")
                #consumed |= {"pixiv_id", "member_name", "member_id"}
                seenurls |= {self.fmt["pixiv_illust"] % data["pixiv_id"]}

            if index == DbIndex.Seiga:
                print(fmt % "Seiga",
                      self.fmt["seiga_illust"] % data["seiga_id"])
                print(fmt % "Member",
                      "｢%s｣" % data["member_name"],
                      "<%s>" % self.fmt["seiga_member"] % data["member_id"])
                consumed |= {"seiga_id", "member_name", "member_id"}
                seenurls |= {self.fmt["seiga_illust"] % data["seiga_id"]}

            if index == DbIndex.DeviantArt:
                print(fmt % "DeviantArt",
                      self.fmt["da_illust"] % data["da_id"])
                print(fmt % "Author",
                      "%s" % data["author_name"],
                      "<%s>" % data["author_url"])
                consumed |= {"da_id", "author_name", "author_url"}
                seenurls |= {self.fmt["da_illust"] % data["da_id"]}

            if index == 18:
                if data.get("creator"):
                    print(fmt % "Creator", "; ".join(data["creator"]))
                names = set()
                for lang in ["eng", "jp"]:
                    key = "%s_name" % lang
                    name = data.get(key)
                    if name and name not in names:
                        print(fmt % "Name (%s)" % lang,
                              name)
                        names.add(name)
                if data.get("source"):
                    print(fmt % "Source", data["source"])
                consumed |= {"creator", "eng_name", "jp_name", "source"}

            for booru in self.boards:
                key = "%s_id" % booru
                if key in data:
                    print(fmt % booru.capitalize(),
                          "<%s>" % self.fmt[key] % data[key])
                    consumed |= {key}
                    seenurls |= {self.fmt[key] % data[key]}
                    if score >= 92 and not swapped:
                        swapped = self.swap(file, self.fmt[key] % data[key], booru)

            if "creator" not in consumed:
                if data.get("creator"):
                    print(fmt % "Creator",
                          "｢%s｣" % data["creator"])
                consumed |= {"creator"}

            if "source" not in consumed:
                if data.get("source"):
                    print(fmt % "Source",
                          "<%s>" % data["source"])
                consumed |= {"source"}

            if "ext_urls" not in consumed:
                for url in data.get("ext_urls", []):
                    if url.startswith("https://danbooru.donmai.us/"):
                        url = url.replace("/post/show/", "/posts/")
                    if url not in seenurls:
                        print(fmt % "URL",
                              "<%s>" % url)
                    seenurls.add(url)
                consumed |= {"ext_urls"}

            if set(data) - consumed:
                pprint("Unparsed fields: %r" % (set(data) - consumed))
                pprint(data)

            print()

        if swapped:
            print("\033[38;5;10m" "✔ original successfully downloaded" "\033[m")
        else:
            print("\033[38;5;9m" "original not downloaded" "\033[m")

creds = get_netrc("saucenao.com", service="api")
if creds:
    s = SauceNao(creds["password"])
else:
    s = SauceNao()

files = sys.argv[1:]
for f in files:
    s.find(f)
