import os
import socket
import sys

from buildbot.plugins import reporters, util
from datetime import timedelta

import loadConfig
from events import Events

# This is work-around for Twisted having a small size limit for patches. See https://bugs.webkit.org/show_bug.cgi?id=198851#c5
from twisted.spread import banana
banana.SIZE_LIMIT = 100 * 1024 * 1024

# This is work-around for https://bugs.webkit.org/show_bug.cgi?id=222361
from buildbot.process.buildstep import BuildStep
BuildStep.warn_deprecated_if_oldstyle_subclass = lambda self, name: None

is_test_mode_enabled = os.getenv('BUILDBOT_PRODUCTION') is None

c = BuildmasterConfig = {}

c['www'] = dict(port='tcp:8010:interface=127.0.0.1', allowed_origins=["*"])
c['www']['custom_templates_dir'] = 'templates'

c['www']['ui_default_config'] = { 
    'Builders.show_workers_name': True,
    'Builders.buildFetchLimit': 1000,
    'Workers.showWorkerBuilders': True,
}

if not is_test_mode_enabled:
    admin_username = os.getenv('EWS_ADMIN_USERNAME')
    admin_password = os.getenv('EWS_ADMIN_PASSWORD')
    if not admin_username or not admin_password:
        print('Environment variables for admin username/password not found. Please ensure these variables are set.')
        sys.exit(1)
    # See https://docs.buildbot.net/current/manual/configuration/www.html#example-configs
    authz = util.Authz(
        allowRules=[util.AnyControlEndpointMatcher(role="admin")],
        roleMatchers=[util.RolesFromEmails(admin=[admin_username])]
    )
    auth = util.UserPasswordAuth({admin_username: admin_password})
    c['www']['auth'] = auth
    c['www']['authz'] = authz

c['protocols'] = {'pb': {'port': 17000}}

c['projectName'] = 'WebKit EWS'
c['projectURL'] = 'https://ews-build.webkit.org/'

if is_test_mode_enabled:
    c['buildbotURL'] = 'http://localhost:8010/'
    c['db_url'] = 'sqlite:///state.sqlite?serialize_access=1'
else:
    c['buildbotURL'] = 'https://ews-build.webkit.org/'
    db_url = os.getenv('DB_URL', None)
    db_name = os.getenv('DB_NAME', None)
    db_username = os.getenv('DB_USERNAME', None)
    db_password = os.getenv('DB_PASSWORD', None)
    if None in [db_url, db_name, db_username, db_password]:
        print('Environment variables for DB not found. Please ensure these variables are set.')
        sys.exit(1)
    # See https://docs.buildbot.net/1.7.0/manual/configuration/global.html#database-specification
    c['db_url'] = 'postgresql://{}:{}@{}/{}'.format(db_username, db_password, db_url, db_name)
    # configure a janitor to delete old logs
    c['configurators'] = [util.JanitorConfigurator(logHorizon=timedelta(weeks=52), hour='1', dayOfWeek='*')]

c['logCompressionMethod'] = 'lz4'
c['buildbotNetUsageData'] = None

loadConfig.loadBuilderConfig(c, is_test_mode_enabled=is_test_mode_enabled)

mail_notifier = reporters.MailNotifier(
    fromaddr='ews-build@webkit.org',
    sendToInterestedUsers=False,
    extraRecipients=['webkit-ews-bot-watchers@group.apple.com'],
    mode=('exception'),
    addPatch=False)

if not is_test_mode_enabled:
    hostname =  socket.gethostname().strip()
    event_reporter = Events(master_hostname=hostname, type_prefix='ews')
    c['services'] = [event_reporter, mail_notifier]
