from site import Site
from abc import abstractmethod
from helper import Helper
from matcher import *


class Kink(Site):
    ARTWORK_ITEM_LIMIT = 8

    id = None
    cookies = None

    helper = Helper()

    def __init__(self, siteId, name, baseUrl):
        Site.__init__(self, siteId, name, baseUrl)

    @abstractmethod
    def create(self):
        pass

    def get_id(self):
        return "{}-{}".format(self.siteId, self.id)

    def set_id(self, id):
        Log("set_id({})".format(id))
        parts = id.split("-")
        self.id = parts[1]
        return self

    def get_url(self):
        return "http://www.kink.com/shoot/{}".format(self.id)

    def init_cookies(self):
        if self.cookies is not None:
            return
        self.cookies = HTTP.CookiesForURL("http://www.kink.com")
        if self.cookies is not None:
            return
#        HTTP.ClearCookies()
        HTTP.Request("http://www.kink.com", headers={'Cookie': 'viewing-preferences=straight%2Cgay'}).content
        self.cookies = HTTP.CookiesForURL("http://www.kink.com")
        if self.cookies is None:
            Log.Error("init_cookies() FAILED!")

    def search(self, results, filename, media, lang, manual):
        self.init_cookies()
        self.update()

        self.helper.set_date_from_filename(self, filename)

        # Initialize best-match search
        words = set(re.findall(r'\W*(\w+)', filename.upper()))
        if self.year is not None:
            # Log("date: {}-{}-{}".format(self.year, self.month, self.day))
            words.add(self.year)
            words.add(self.month)
            words.add(self.day)
        bestMatch = len(words)
        Log("Words we look for: {}".format(words))

        # See if the filename contains a kink.com shoot number
        shootId = None
        shootIds = re.findall(r'\D*(\d\d\d\d\d)\D*', filename)
        if len(shootIds) == 1:
            shootId = self.siteId + "-" + str(shootIds[0])

        date = self.get_date()
        for id in Dict[self.siteId]['idToRecordMap']:
            record = Dict[self.siteId]['idToRecordMap'][id]
            if record['date'] == date:
                Log("Date Match -- Creating 100% match on: {}".format(record['title']))
                results.Append(MetadataSearchResult(id=id, name=record['title'], score=100,
                                                    year=int(self.year), lang=lang))
                continue

            if shootId is not None and id == shootId:
                Log("Shoot ID Match -- Creating 90% match on: {}".format(record['title']))
                results.Append(MetadataSearchResult(id=id, name=record['title'], score=90,
                                                    year=record['date'].split("-")[0], lang=lang))
                continue

            intersection = words & record['words']
            percentage = (len(intersection) * 100) / bestMatch
            # Log("{} -> {} or {}".format(record['words'], intersection, percentage))
            if percentage > 40:
                Log("Creating {}% match on: {}".format(percentage, record['title']))
                results.Append(MetadataSearchResult(id=id, name=record['title'], score=percentage,
                                                    year=record['date'].split("-")[0], lang=lang))


    def update(self):
        if not self.siteId in Dict:
            Dict[self.siteId] = {}
            Dict[self.siteId]['idToRecordMap'] = {}
            Dict.Save()

        page = 1
        matched_movie = False
        changed = False
        # cookies = HTTP.CookiesForURL("http://www.kink.com")
        while not matched_movie:
            url = "http://www.kink.com/channel/{}/latest/page/{}".format(self.siteId.lower(), page)
            req = HTTP.Request(url, headers = {'Cookie': self.cookies})
            html = HTML.ElementFromString(req.content)

            shoots = html.xpath("//div[@class='shoot']")
            for shoot in shoots:
                shoot_href = shoot.xpath("./div[@class='shoot-thumb-image']/a/@href")[0]
                self.id = str(shoot_href).split("/")[2]

                date = shoot.xpath("./div[@class='shoot-thumb-info']/div[@class='top-row-info']/div[@class='date']/text()")[0]
                date = Datetime.ParseDate(str(date).strip()).date()
                self.year = "{:04d}".format(date.year)
                self.month = "{:02d}".format(date.month)
                self.day = "{:02d}".format(date.day)

                id = self.get_id()
                if id in Dict[self.siteId]['idToRecordMap']:
                    matched_movie = True
                    continue

                Log("update - Indexing {}".format(self.id))

                title = str(shoot.xpath("./div[@class='shoot-thumb-info']/div[@class='shoot-thumb-title']/div/a/text()")[0]).strip()
                words = set(re.findall(r'\W*(\w+)', title.upper()))

                models = shoot.xpath("./div[@class='shoot-thumb-info']/div[@class='shoot-thumb-models']/a/text()")
                modelList = []
                for model in models:
                    name = str(model).replace(",\xc2\xa0", "").strip()
                    modelList.append(name)
                    for word in name.split(" "):
                        words.add(word.upper())
                Log("{} - {} - {}".format(shoot_href, self.get_date(), title))

                words.add(self.year)
                words.add(self.month)
                words.add(self.day)

                if len(modelList) == 0:
                    t = title
                elif len(modelList) == 1:
                    t = "{} ({})".format(title, modelList[0])
                else:
                    t = "{} ({}, {})".format(title, modelList[0], modelList[1])

                Dict[self.siteId]['idToRecordMap'][id] = {}
                Dict[self.siteId]['idToRecordMap'][id]['words'] = words
                Dict[self.siteId]['idToRecordMap'][id]['date'] = self.get_date()
                Dict[self.siteId]['idToRecordMap'][id]['title'] = t
                changed = True

            if len(shoots) == 20:
                page += 1
            else:
                break

        if changed:
            Dict.Save()

    def get_metadata(self, metadata, media, lang, force):
        self.init_cookies()

        record = Dict[self.siteId]['idToRecordMap'][self.get_id()]

        # Retrieve the page
        href = self.get_url()
        html = HTML.ElementFromURL(href, headers = {'Cookie': self.cookies})

        # use site name as movie studio
        metadata.studio = self.name

        # add site name to genres
        metadata.genres.clear()
        metadata.genres.add(self.name)

        # add channels to genres
        # add other tags to collections
        metadata.collections.clear()
        tags = html.xpath('//div[@class="shoot-info"]//a[starts-with(@href,"/tag/")]')
        for tag in tags:
            if tag.get('href').endswith(':channel'):
                metadata.genres.add(tag.text_content().strip())
            else:
                metadata.collections.add(tag.text_content().strip())

        # set movie title to shoot title
        # metadata.title = html.xpath('//div[@class="shoot-info"]//h1')[0].text_content() + " (" + record['date'] + ")"
        t = html.xpath('//div[@class="shoot-info"]/h1/text()')
        if len(t) > 0:
            Log("Title found")
            Log("Date: {}".format(record['date']))
            metadata.title = "{} ({})".format(t[0], record['date'])
        else:
            Log("Title not found")

        # set content rating to X
        metadata.content_rating = 'X'

        # set episode ID as tagline for easy visibility
        metadata.tagline = metadata.studio + " – " + self.id

        # set movie release date to shoot release date
        try:
            release_date = html.xpath('//div[@class="shoot-info"]//p[contains(.,"date:")]')[0].text_content().split('date: ', 1)[1]
            metadata.originally_available_at = Datetime.ParseDate(release_date).date()
            metadata.year = metadata.originally_available_at.year
        except: pass

        # Add posters and backdrops
        self.process_images(metadata, html)

        # summary
        try:
            metadata.summary = ""
            summary = html.xpath('//div[@class="shoot-info"]/div[@class="description"]')
            if len(summary) > 0:
                for paragraph in summary:
                    metadata.summary = metadata.summary + paragraph.text_content().strip().replace('<br>',"\n") + "\n"
                metadata.summary.strip()
        except: pass

        # director
        try:
            metadata.directors.clear()
            director_id = html.xpath('//div[@class="shoot-page"]/@data-director')[0]
            director_html = HTML.ElementFromURL("http://www.kink.com/model/%s" % director_id, headers={'Cookie': self.cookies})
            # 'viewing-preferences=straight%2Cgay'})
            director_name = director_html.xpath('//h1[@class="page-title"]')[0].text_content()
            try:
                director = metadata.directors.new()
                director.name = director_name
            except:
                try:
                    metadata.directors.add(director_name)
                except: pass
        except: pass

        # starring
        try:
            starring = html.xpath('//p[@class="starring"]/*[@class="names"]/a')
            metadata.roles.clear()
            for member in starring:
                role = metadata.roles.new()
                lename = member.text_content().strip()
                try:
                    role.name = lename
                except:
                    try:
                        role.actor = lename
                    except: pass
        except: pass

        # rating
        # cookies = self.cookies
        # Log(cookies)
        # cookies.add('viewing-preferences=straight%2Cgay')
        # Log(cookies)
        rating_dict = JSON.ObjectFromURL(url='http://www.kink.com/api/ratings/%s' % self.id, headers={'Cookie': self.cookies})
        metadata.rating = float(rating_dict['average']) * 2

    def process_images(self, metadata, html):
        valid_posters = list()
        valid_backdrops = list()
        posterIndex = 0
        backdropIndex = 0
        posterUrls = html.xpath('//video/@poster')
        for posterUrl in posterUrls:
            url = str(posterUrl).strip()
            if posterIndex < self.ARTWORK_ITEM_LIMIT:
                valid_posters.append(self.add_poster(metadata, url, posterIndex))
            if backdropIndex < self.ARTWORK_ITEM_LIMIT:
                valid_backdrops.append(self.add_backdrop(metadata, url, backdropIndex))
            posterIndex += 1
            backdropIndex += 1
        posterUrls = html.xpath('//div[@id="previewImages"]//img/@src')
        for posterUrl in posterUrls:
            url = str(posterUrl).strip()
            if posterIndex < self.ARTWORK_ITEM_LIMIT:
                valid_posters.append(self.add_poster(metadata, url, posterIndex))
            if backdropIndex < self.ARTWORK_ITEM_LIMIT:
                valid_backdrops.append(self.add_backdrop(metadata, url, backdropIndex))
            posterIndex += 1
            backdropIndex += 1
        metadata.posters.validate_keys(valid_posters)
        metadata.art.validate_keys(valid_backdrops)

    def add_poster(self, metadata, url, index):
        thumbnail = re.sub(r'/h/[0-9]{3,3}/', r'/h/410/', url)
        full = re.sub(r'/h/[0-9]{3,3}/', r'/h/830/', url)
        Log("Adding new poster ({}): {}".format(index, full))
        metadata.posters[full] = Proxy.Preview(HTTP.Request(thumbnail), sort_order=index)
        return full

    def add_backdrop(self, metadata, url, index):
        if index >= self.ARTWORK_ITEM_LIMIT:
            return
        thumbnail = re.sub(r'/h/[0-9]{3,3}/', r'/h/410/', url)
        full = re.sub(r'/h/[0-9]{3,3}/', r'/h/830/', url)
        Log("Adding new backdrop ({}): {}".format(index, full))
        metadata.art[full] = Proxy.Preview(HTTP.Request(thumbnail), sort_order=index)
        return full


#
# BDSM Channels
#


class Hogtied(Kink):
    def __init__(self):
        Kink.__init__(self, "HOGTIED", "Hogtied", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*HOGTIED.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*HOGTIED.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^HT\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WHT\W.*", re.IGNORECASE))

    def create(self):
        return Hogtied()


class DeviceBondage(Kink):
    def __init__(self):
        Kink.__init__(self, "DEVICEBONDAGE", "Device Bondage", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*DEVICEBONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*DEVICEBONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*DEVICE BONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*DEVICE BONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^DB\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WDB\W.*", re.IGNORECASE))

    def create(self):
        return DeviceBondage()


class FamiliesTied(Kink):
    def __init__(self):
        Kink.__init__(self, "FAMILIESTIED", "Families Tied", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*FAMILIESTIED.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*FAMILIESTIED.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*FAMILIES TIED.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*FAMILIES TIED.*", re.IGNORECASE))

    def create(self):
        return FamiliesTied()


class TheUpperFloor(Kink):
    def __init__(self):
        Kink.__init__(self, "THEUPPERFLOOR", "The Upper Floor", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*THEUPPERFLOOR.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*THEUPPERFLOOR.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*UPPER FLOOR.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*UPPER FLOOR.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^TUF\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WTUF\W.*", re.IGNORECASE))

    def create(self):
        return TheUpperFloor()


class TheTrainingOfO(Kink):
    def __init__(self):
        Kink.__init__(self, "THETRAININGOFO", "The Training Of O", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*THETRAININGOFO.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*THETRAININGOFO.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*TRAINING OF O.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*TRAINING OF O.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^TTOO\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WTTOO\W.*", re.IGNORECASE))

    def create(self):
        return TheTrainingOfO()


class KinkFeatures(Kink):
    def __init__(self):
        Kink.__init__(self, "KINKFEATURES", "Kink Features", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*KINKFEATURES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*KINKFEATURES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*KINK FEATURES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*KINK FEATURES.*", re.IGNORECASE))

    def create(self):
        return KinkUniversity()


class KinkUniversity(Kink):
    def __init__(self):
        Kink.__init__(self, "KINKUNIVERSITY", "Kink University", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*UNIVERSITY.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*UNIVERSITY.*", re.IGNORECASE))

    def create(self):
        return KinkUniversity()


class SadisticRope(Kink):
    def __init__(self):
        Kink.__init__(self, "SADISTICROPE", "Sadistic Rope", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*SADISTICROPE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*SADISTICROPE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*SADISTIC ROPE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*SADISTIC ROPE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^SR\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WSR\W.*", re.IGNORECASE))

    def create(self):
        return SadisticRope()


class WaterBondage(Kink):
    def __init__(self):
        Kink.__init__(self, "WATERBONDAGE", "Water Bondage", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*WATERBONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*WATERBONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*WATER BONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*WATER BONDAGE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^WB\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WWB\W.*", re.IGNORECASE))

    def create(self):
        return WaterBondage()


#
# Hardcore Channels
#


class SexAndSubmission(Kink):
    def __init__(self):
        Kink.__init__(self, "SEXANDSUBMISSION", "Sex and Submission", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*SEXANDSUBMISSION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*SEXANDSUBMISSION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*SEX AND SUBMISSION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*SEX AND SUBMISSION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^SAS\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WSAS\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WSAS\..*", re.IGNORECASE))

    def create(self):
        return SexAndSubmission()


class FuckingMachines(Kink):
    def __init__(self):
        Kink.__init__(self, "FUCKINGMACHINES", "Fucking Machines", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*FUCKINGMACHINES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*FUCKINGMACHINES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*FUCKING MACHINES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*FUCKING MACHINES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^FM\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WFM\W.*", re.IGNORECASE))

    def create(self):
        return FuckingMachines()


class PublicDisgrace(Kink):
    def __init__(self):
        Kink.__init__(self, "PUBLICDISGRACE", "Public Disgrace", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*PUBLICDISGRACE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*PUBLICDISGRACE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*PUBLIC DISGRACE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*PUBLIC DISGRACE.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^PD\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WPD\W.*", re.IGNORECASE))

    def create(self):
        return PublicDisgrace()


class HardcoreGangBang(Kink):
    def __init__(self):
        Kink.__init__(self, "HARDCOREGANGBANG", "Hardcore Gangbang", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*HARDCOREGANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*HARDCOREGANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*HARDCORE GANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*HARDCORE GANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*HARDCORE GANG BANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*HARDCORE GANG BANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^HGB\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WHGB\W.*", re.IGNORECASE))

    def create(self):
        return HardcoreGangBang()


class BoundGangBangs(Kink):
    def __init__(self):
        Kink.__init__(self, "BOUNDGANGBANGS", "Bound Gang Bangs", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*BOUNDGANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*BOUNDGANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*BOUND GANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*BOUND GANGBANG.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*BOUNDGANGBANGS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*BOUNDGANGBANGS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*BOUND GANGBANGS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*BOUND GANGBANGS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^BGB\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WBGB\W.*", re.IGNORECASE))

    def create(self):
        return BoundGangBangs()


class DungeonSex(Kink):
    def __init__(self):
        Kink.__init__(self, "DUNGEONSEX", "Dungeon Sex", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*DUNGEONSEX.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*DUNGEONSEX.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*DUNGEON SEX.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*DUNGEON SEX.*", re.IGNORECASE))

    def create(self):
        return DungeonSex()


class AnimatedKink(Kink):
    def __init__(self):
        Kink.__init__(self, "ANIMATEDKINK", "Animated Kink", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*ANIMATEDKINK.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*ANIMATEDKINK.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*ANIMATED KINK.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*ANIMATED KINK.*", re.IGNORECASE))

    def create(self):
        return AnimatedKink()


#
# FemDom Channels
#


class WhippedAss(Kink):
    def __init__(self):
        Kink.__init__(self, "WHIPPEDASS", "Whipped Ass", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*WHIPPEDASS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*WHIPPEDASS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*WHIPPED ASS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*WHIPPED ASS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^WA\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WWA\W.*", re.IGNORECASE))

    def create(self):
        return WhippedAss()


class DivineBitches(Kink):
    def __init__(self):
        Kink.__init__(self, "DIVINEBITCHES", "Divine Bitches", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*DIVINEBITCHES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*DIVINEBITCHES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*DIVINE BITCHES.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*DIVINE BITCHES.*", re.IGNORECASE))
        # Conflicts with DeviceBondage!
        # self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^DB\W.*", re.IGNORECASE))
        # self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WDB\W.*", re.IGNORECASE))

    def create(self):
        return DivineBitches()


class UltimateSurrender(Kink):
    def __init__(self):
        Kink.__init__(self, "ULTIMATESURRENDER", "Ultimate Surrender", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*ULTIMATESURRENDER.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*ULTIMATESURRENDER.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*ULTIMATE SURRENDER.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*ULTIMATE SURRENDER.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^US\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WUS\W.*", re.IGNORECASE))

    def create(self):
        return UltimateSurrender()


class EverythingButt(Kink):
    def __init__(self):
        Kink.__init__(self, "EVERYTHINGBUTT", "Everything Butt", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*EVERYTHINGBUTT.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*EVERYTHINGBUTT.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*EVERYTHING BUTT.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*EVERYTHING BUTT.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^EB\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WEB\W.*", re.IGNORECASE))

    def create(self):
        return EverythingButt()


class ElectroSluts(Kink):
    def __init__(self):
        Kink.__init__(self, "ELECTROSLUTS", "Electro Sluts", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*ELECTROSLUTS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*ELECTROSLUTS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*ELECTRO SLUTS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*ELECTRO SLUTS.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^ES\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WES\W.*", re.IGNORECASE))

    def create(self):
        return ElectroSluts()


class MenInPain(Kink):
    def __init__(self):
        Kink.__init__(self, "MENINPAIN", "Men In Pain", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*MENINPAIN.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*MENINPAIN.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*MEN IN PAIN.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*MEN IN PAIN.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^MIP\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WMIP\W.*", re.IGNORECASE))

    def create(self):
        return MenInPain()


class WiredPussy(Kink):
    def __init__(self):
        Kink.__init__(self, "WIREDPUSSY", "Wired Pussy", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*WIREDPUSSY.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*WIREDPUSSY.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*WIRED PUSSY.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*WIRED PUSSY.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^WP\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WWP\W.*", re.IGNORECASE))

    def create(self):
        return WiredPussy()


class FootWorship(Kink):
    def __init__(self):
        Kink.__init__(self, "FOOTWORSHIP", "Foot Worship", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*FOOTWORSHIP.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*FOOTWORSHIP.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*FOOT WORSHIP.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*FOOT WORSHIP.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^FW\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WFW\W.*", re.IGNORECASE))

    def create(self):
        return FootWorship()


#
# TS Channels
#


class TSSeduction(Kink):
    def __init__(self):
        Kink.__init__(self, "TSSEDUCTION", "TS Seduction", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*TSSEDUCTION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*TSSEDUCTION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*TS SEDUCTION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*TS SEDUCTION.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^TSS\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WTSS\W.*", re.IGNORECASE))

    def create(self):
        return TSSeduction()


class TSPussyHunters(Kink):
    def __init__(self):
        Kink.__init__(self, "TSPUSSYHUNTERS", "TS Pussy Hunters", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*TSPussyHunters.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*TSPussyHunters.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*TS Pussy Hunters.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*TS Pussy Hunters.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^TSPH\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WTSPH\W.*", re.IGNORECASE))

    def create(self):
        return TSPussyHunters()


#
# Kinkmen Channels
#


class BoundGods(Kink):
    def __init__(self):
        Kink.__init__(self, "BOUNDGODS", "Bound Gods", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*BoundGods.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*BoundGods.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*Bound Gods.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*Bound Gods.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^BG\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WBG\W.*", re.IGNORECASE))

    def create(self):
        return BoundGods()


class MenOnEdge(Kink):
    def __init__(self):
        Kink.__init__(self, "MENONEDGE", "Men On Edge", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*MenOnEdge.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*MenOnEdge.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*Men On Edge.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*Men On Edge.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^MOE\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WMOE\W.*", re.IGNORECASE))

    def create(self):
        return MenOnEdge()


class NakedKombat(Kink):
    def __init__(self):
        Kink.__init__(self, "NakedKombat", "Naked Kombat", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*NakedKombat.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*NakedKombat.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*Naked Kombat.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*Naked Kombat.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^NK\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WNK\W.*", re.IGNORECASE))

    def create(self):
        return NakedKombat()


class BoundInPublic(Kink):
    def __init__(self):
        Kink.__init__(self, "BOUNDINPUBLIC", "BoundInPublic", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*BoundInPublic.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*BoundInPublic.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*Bound In Public.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*Bound In Public.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^NIP\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WBIP\W.*", re.IGNORECASE))

    def create(self):
        return BoundInPublic()


class ThirthyMinutesOfTorment(Kink):
    def __init__(self):
        Kink.__init__(self, "30MINUTESOFTORMENT", "30 Minutes Of Torment", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*MinutesOfTorment.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*MinutesOfTorment.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*Minutes Of Torment.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*Minutes Of Torment.*", re.IGNORECASE))
        # Unknown
        # self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^NIP\W.*", re.IGNORECASE))
        # self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WBIP\W.*", re.IGNORECASE))

    def create(self):
        return ThirthyMinutesOfTorment()


class ButtMachineBoys(Kink):
    def __init__(self):
        Kink.__init__(self, "BUTTMACHINEBOYS", "Butt Machine Boys", "")
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*ButtMachineBoys.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*ButtMachineBoys.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Filename, ".*Butt Machine Boys.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.High, MatchType.Directory, ".*Butt Machine Boys.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, "^BMB\W.*", re.IGNORECASE))
        self.patterns.append(Pattern(self, MatchPriority.Low, MatchType.Filename, ".*\WBMB\W.*", re.IGNORECASE))

    def create(self):
        return ButtMachineBoys()
