import base64
import os
import time

import requests

import gitlab

LOGIN = 'root'
PASSWORD = '5iveL!fe'

SSH_KEY = ("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZAjAX8vTiHD7Yi3/EzuVaDChtih"
           "79HyJZ6H9dEqxFfmGA1YnncE0xujQ64TCebhkYJKzmTJCImSVkOu9C4hZgsw6eE76n"
           "+Cg3VwEeDUFy+GXlEJWlHaEyc3HWioxgOALbUp3rOezNh+d8BDwwqvENGoePEBsz5l"
           "a6WP5lTi/HJIjAl6Hu+zHgdj1XVExeH+S52EwpZf/ylTJub0Bl5gHwf/siVE48mLMI"
           "sqrukXTZ6Zg+8EHAIvIQwJ1dKcXe8P5IoLT7VKrbkgAnolS0I8J+uH7KtErZJb5oZh"
           "S4OEwsNpaXMAr+6/wWSpircV2/e7sFLlhlKBC4Iq1MpqlZ7G3p foo@bar")
DEPLOY_KEY = ("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFdRyjJQh+1niBpXqE2I8dzjG"
              "MXFHlRjX9yk/UfOn075IdaockdU58sw2Ai1XIWFpZpfJkW7z+P47ZNSqm1gzeXI"
              "rtKa9ZUp8A7SZe8vH4XVn7kh7bwWCUirqtn8El9XdqfkzOs/+FuViriUWoJVpA6"
              "WZsDNaqINFKIA5fj/q8XQw+BcS92L09QJg9oVUuH0VVwNYbU2M2IRmSpybgC/gu"
              "uWTrnCDMmLItksATifLvRZwgdI8dr+q6tbxbZknNcgEPrI2jT0hYN9ZcjNeWuyv"
              "rke9IepE7SPBT41C+YtUX4dfDZDmczM1cE0YL/krdUCfuZHMa4ZS2YyNd6slufc"
              "vn bar@foo")

GPG_KEY = '''-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFn5mzYBCADH6SDVPAp1zh/hxmTi0QplkOfExBACpuY6OhzNdIg+8/528b3g
Y5YFR6T/HLv/PmeHskUj21end1C0PNG2T9dTx+2Vlh9ISsSG1kyF9T5fvMR3bE0x
Dl6S489CXZrjPTS9SHk1kF+7dwjUxLJyxF9hPiSihFefDFu3NeOtG/u8vbC1mewQ
ZyAYue+mqtqcCIFFoBz7wHKMWjIVSJSyTkXExu4OzpVvy3l2EikbvavI3qNz84b+
Mgkv/kiBlNoCy3CVuPk99RYKZ3lX1vVtqQ0OgNGQvb4DjcpyjmbKyibuZwhDjIOh
au6d1OyEbayTntd+dQ4j9EMSnEvm/0MJ4eXPABEBAAG0G0dpdGxhYlRlc3QxIDxm
YWtlQGZha2UudGxkPokBNwQTAQgAIQUCWfmbNgIbAwULCQgHAgYVCAkKCwIEFgID
AQIeAQIXgAAKCRBgxELHf8f3hF3yB/wNJlWPKY65UsB4Lo0hs1OxdxCDqXogSi0u
6crDEIiyOte62pNZKzWy8TJcGZvznRTZ7t8hXgKFLz3PRMcl+vAiRC6quIDUj+2V
eYfwaItd1lUfzvdCaC7Venf4TQ74f5vvNg/zoGwE6eRoSbjlLv9nqsxeA0rUBUQL
LYikWhVMP3TrlfgfduYvh6mfgh57BDLJ9kJVpyfxxx9YLKZbaas9sPa6LgBtR555
JziUxHmbEv8XCsUU8uoFeP1pImbNBplqE3wzJwzOMSmmch7iZzrAwfN7N2j3Wj0H
B5kQddJ9dmB4BbU0IXGhWczvdpxboI2wdY8a1JypxOdePoph/43iuQENBFn5mzYB
CADnTPY0Zf3d9zLjBNgIb3yDl94uOcKCq0twNmyjMhHzGqw+UMe9BScy34GL94Al
xFRQoaL+7P8hGsnsNku29A/VDZivcI+uxTx4WQ7OLcn7V0bnHV4d76iky2ufbUt/
GofthjDs1SonePO2N09sS4V4uK0d5N4BfCzzXgvg8etCLxNmC9BGt7AaKUUzKBO4
2QvNNaC2C/8XEnOgNWYvR36ylAXAmo0sGFXUsBCTiq1fugS9pwtaS2JmaVpZZ3YT
pMZlS0+SjC5BZYFqSmKCsA58oBRzCxQz57nR4h5VEflgD+Hy0HdW0UHETwz83E6/
U0LL6YyvhwFr6KPq5GxinSvfABEBAAGJAR8EGAEIAAkFAln5mzYCGwwACgkQYMRC
x3/H94SJgwgAlKQb10/xcL/epdDkR7vbiei7huGLBpRDb/L5fM8B5W77Qi8Xmuqj
cCu1j99ZCA5hs/vwVn8j8iLSBGMC5gxcuaar/wtmiaEvT9fO/h6q4opG7NcuiJ8H
wRj8ccJmRssNqDD913PLz7T40Ts62blhrEAlJozGVG/q7T3RAZcskOUHKeHfc2RI
YzGsC/I9d7k6uxAv1L9Nm5F2HaAQDzhkdd16nKkGaPGR35cT1JLInkfl5cdm7ldN
nxs4TLO3kZjUTgWKdhpgRNF5hwaz51ZjpebaRf/ZqRuNyX4lIRolDxzOn/+O1o8L
qG2ZdhHHmSK2LaQLFiSprUkikStNU9BqSQ==
=5OGa
-----END PGP PUBLIC KEY BLOCK-----'''
AVATAR_PATH = os.path.join(os.path.dirname(__file__), 'avatar.png')


# token authentication from config file
gl = gitlab.Gitlab.from_config(config_files=['/tmp/python-gitlab.cfg'])
gl.auth()
assert(isinstance(gl.user, gitlab.v4.objects.CurrentUser))

# markdown (need to wait for gitlab 11 to enable the test)
# html = gl.markdown('foo')
# assert('foo' in html)

success, errors = gl.lint('Invalid')
assert(success is False)
assert(errors)

# sidekiq
out = gl.sidekiq.queue_metrics()
assert(isinstance(out, dict))
assert('pages' in out['queues'])
out = gl.sidekiq.process_metrics()
assert(isinstance(out, dict))
assert('hostname' in out['processes'][0])
out = gl.sidekiq.job_stats()
assert(isinstance(out, dict))
assert('processed' in out['jobs'])
out = gl.sidekiq.compound_metrics()
assert(isinstance(out, dict))
assert('jobs' in out)
assert('processes' in out)
assert('queues' in out)

# settings
settings = gl.settings.get()
settings.default_projects_limit = 42
settings.save()
settings = gl.settings.get()
assert(settings.default_projects_limit == 42)

# users
new_user = gl.users.create({'email': 'foo@bar.com', 'username': 'foo',
                            'name': 'foo', 'password': 'foo_password',
                            'avatar': open(AVATAR_PATH, 'rb')})
avatar_url = new_user.avatar_url.replace('gitlab.test', 'localhost:8080')
uploaded_avatar = requests.get(avatar_url).content
assert(uploaded_avatar == open(AVATAR_PATH, 'rb').read())
users_list = gl.users.list()
for user in users_list:
    if user.username == 'foo':
        break
assert(new_user.username == user.username)
assert(new_user.email == user.email)

new_user.block()
new_user.unblock()

# user projects list
assert(len(new_user.projects.list()) == 0)

# events list
new_user.events.list()

foobar_user = gl.users.create(
    {'email': 'foobar@example.com', 'username': 'foobar',
     'name': 'Foo Bar', 'password': 'foobar_password'})

assert gl.users.list(search='foobar')[0].id == foobar_user.id
expected = [new_user, foobar_user]
actual = list(gl.users.list(search='foo'))
assert len(expected) == len(actual)
assert len(gl.users.list(search='asdf')) == 0
foobar_user.bio = 'This is the user bio'
foobar_user.save()

# GPG keys
gkey = new_user.gpgkeys.create({'key': GPG_KEY})
assert(len(new_user.gpgkeys.list()) == 1)
# Seems broken on the gitlab side
# gkey = new_user.gpgkeys.get(gkey.id)
gkey.delete()
assert(len(new_user.gpgkeys.list()) == 0)

# SSH keys
key = new_user.keys.create({'title': 'testkey', 'key': SSH_KEY})
assert(len(new_user.keys.list()) == 1)
key.delete()
assert(len(new_user.keys.list()) == 0)

# emails
email = new_user.emails.create({'email': 'foo2@bar.com'})
assert(len(new_user.emails.list()) == 1)
email.delete()
assert(len(new_user.emails.list()) == 0)

# custom attributes
attrs = new_user.customattributes.list()
assert(len(attrs) == 0)
attr = new_user.customattributes.set('key', 'value1')
assert(len(gl.users.list(custom_attributes={'key': 'value1'})) == 1)
assert(attr.key == 'key')
assert(attr.value == 'value1')
assert(len(new_user.customattributes.list()) == 1)
attr = new_user.customattributes.set('key', 'value2')
attr = new_user.customattributes.get('key')
assert(attr.value == 'value2')
assert(len(new_user.customattributes.list()) == 1)
attr.delete()
assert(len(new_user.customattributes.list()) == 0)

# impersonation tokens
user_token = new_user.impersonationtokens.create(
    {'name': 'token1', 'scopes': ['api', 'read_user']})
l = new_user.impersonationtokens.list(state='active')
assert(len(l) == 1)
user_token.delete()
l = new_user.impersonationtokens.list(state='active')
assert(len(l) == 0)
l = new_user.impersonationtokens.list(state='inactive')
assert(len(l) == 1)

new_user.delete()
foobar_user.delete()
assert(len(gl.users.list()) == 3)

# current user mail
mail = gl.user.emails.create({'email': 'current@user.com'})
assert(len(gl.user.emails.list()) == 1)
mail.delete()
assert(len(gl.user.emails.list()) == 0)

# current user GPG keys
gkey = gl.user.gpgkeys.create({'key': GPG_KEY})
assert(len(gl.user.gpgkeys.list()) == 1)
# Seems broken on the gitlab side
gkey = gl.user.gpgkeys.get(gkey.id)
gkey.delete()
assert(len(gl.user.gpgkeys.list()) == 0)

# current user key
key = gl.user.keys.create({'title': 'testkey', 'key': SSH_KEY})
assert(len(gl.user.keys.list()) == 1)
key.delete()
assert(len(gl.user.keys.list()) == 0)

# templates
assert(gl.dockerfiles.list())
dockerfile = gl.dockerfiles.get('Node')
assert(dockerfile.content is not None)

assert(gl.gitignores.list())
gitignore = gl.gitignores.get('Node')
assert(gitignore.content is not None)

assert(gl.gitlabciymls.list())
gitlabciyml = gl.gitlabciymls.get('Nodejs')
assert(gitlabciyml.content is not None)

assert(gl.licenses.list())
license = gl.licenses.get('bsd-2-clause', project='mytestproject',
                          fullname='mytestfullname')
assert('mytestfullname' in license.content)

# groups
user1 = gl.users.create({'email': 'user1@test.com', 'username': 'user1',
                         'name': 'user1', 'password': 'user1_pass'})
user2 = gl.users.create({'email': 'user2@test.com', 'username': 'user2',
                         'name': 'user2', 'password': 'user2_pass'})
group1 = gl.groups.create({'name': 'group1', 'path': 'group1'})
group2 = gl.groups.create({'name': 'group2', 'path': 'group2'})

p_id = gl.groups.list(search='group2')[0].id
group3 = gl.groups.create({'name': 'group3', 'path': 'group3', 'parent_id': p_id})

assert(len(gl.groups.list()) == 3)
assert(len(gl.groups.list(search='oup1')) == 1)
assert(group3.parent_id == p_id)
assert(group2.subgroups.list()[0].id == group3.id)

group1.members.create({'access_level': gitlab.const.OWNER_ACCESS,
                       'user_id': user1.id})
group1.members.create({'access_level': gitlab.const.GUEST_ACCESS,
                       'user_id': user2.id})

group2.members.create({'access_level': gitlab.const.OWNER_ACCESS,
                       'user_id': user2.id})

# Administrator belongs to the groups
assert(len(group1.members.list()) == 3)
assert(len(group2.members.list()) == 2)

group1.members.delete(user1.id)
assert(len(group1.members.list()) == 2)
member = group1.members.get(user2.id)
member.access_level = gitlab.const.OWNER_ACCESS
member.save()
member = group1.members.get(user2.id)
assert(member.access_level == gitlab.const.OWNER_ACCESS)

group2.members.delete(gl.user.id)

# group custom attributes
attrs = group2.customattributes.list()
assert(len(attrs) == 0)
attr = group2.customattributes.set('key', 'value1')
assert(len(gl.groups.list(custom_attributes={'key': 'value1'})) == 1)
assert(attr.key == 'key')
assert(attr.value == 'value1')
assert(len(group2.customattributes.list()) == 1)
attr = group2.customattributes.set('key', 'value2')
attr = group2.customattributes.get('key')
assert(attr.value == 'value2')
assert(len(group2.customattributes.list()) == 1)
attr.delete()
assert(len(group2.customattributes.list()) == 0)

# group notification settings
settings = group2.notificationsettings.get()
settings.level = 'disabled'
settings.save()
settings = group2.notificationsettings.get()
assert(settings.level == 'disabled')

# group badges
badge_image = 'http://example.com'
badge_link = 'http://example/img.svg'
badge = group2.badges.create({'link_url': badge_link, 'image_url': badge_image})
assert(len(group2.badges.list()) == 1)
badge.image_url = 'http://another.example.com'
badge.save()
badge = group2.badges.get(badge.id)
assert(badge.image_url == 'http://another.example.com')
badge.delete()
assert(len(group2.badges.list()) == 0)

# group milestones
gm1 = group1.milestones.create({'title': 'groupmilestone1'})
assert(len(group1.milestones.list()) == 1)
gm1.due_date = '2020-01-01T00:00:00Z'
gm1.save()
gm1.state_event = 'close'
gm1.save()
gm1 = group1.milestones.get(gm1.id)
assert(gm1.state == 'closed')
assert(len(gm1.issues()) == 0)
assert(len(gm1.merge_requests()) == 0)

# group variables
group1.variables.create({'key': 'foo', 'value': 'bar'})
g_v = group1.variables.get('foo')
assert(g_v.value == 'bar')
g_v.value = 'baz'
g_v.save()
g_v = group1.variables.get('foo')
assert(g_v.value == 'baz')
assert(len(group1.variables.list()) == 1)
g_v.delete()
assert(len(group1.variables.list()) == 0)

# hooks
hook = gl.hooks.create({'url': 'http://whatever.com'})
assert(len(gl.hooks.list()) == 1)
hook.delete()
assert(len(gl.hooks.list()) == 0)

# projects
admin_project = gl.projects.create({'name': 'admin_project'})
gr1_project = gl.projects.create({'name': 'gr1_project',
                                  'namespace_id': group1.id})
gr2_project = gl.projects.create({'name': 'gr2_project',
                                  'namespace_id': group2.id})
sudo_project = gl.projects.create({'name': 'sudo_project'}, sudo=user1.name)

assert(len(gl.projects.list(owned=True)) == 2)
assert(len(gl.projects.list(search="admin")) == 1)

# test pagination
l1 = gl.projects.list(per_page=1, page=1)
l2 = gl.projects.list(per_page=1, page=2)
assert(len(l1) == 1)
assert(len(l2) == 1)
assert(l1[0].id != l2[0].id)

# group custom attributes
attrs = admin_project.customattributes.list()
assert(len(attrs) == 0)
attr = admin_project.customattributes.set('key', 'value1')
assert(len(gl.projects.list(custom_attributes={'key': 'value1'})) == 1)
assert(attr.key == 'key')
assert(attr.value == 'value1')
assert(len(admin_project.customattributes.list()) == 1)
attr = admin_project.customattributes.set('key', 'value2')
attr = admin_project.customattributes.get('key')
assert(attr.value == 'value2')
assert(len(admin_project.customattributes.list()) == 1)
attr.delete()
assert(len(admin_project.customattributes.list()) == 0)

# project pages domains
domain = admin_project.pagesdomains.create({'domain': 'foo.domain.com'})
assert(len(admin_project.pagesdomains.list()) == 1)
assert(len(gl.pagesdomains.list()) == 1)
domain = admin_project.pagesdomains.get('foo.domain.com')
assert(domain.domain == 'foo.domain.com')
domain.delete()
assert(len(admin_project.pagesdomains.list()) == 0)

# project content (files)
admin_project.files.create({'file_path': 'README',
                            'branch': 'master',
                            'content': 'Initial content',
                            'commit_message': 'Initial commit'})
readme = admin_project.files.get(file_path='README', ref='master')
readme.content = base64.b64encode(b"Improved README").decode()
time.sleep(2)
readme.save(branch="master", commit_message="new commit")
readme.delete(commit_message="Removing README", branch="master")

admin_project.files.create({'file_path': 'README.rst',
                            'branch': 'master',
                            'content': 'Initial content',
                            'commit_message': 'New commit'})
readme = admin_project.files.get(file_path='README.rst', ref='master')
# The first decode() is the ProjectFile method, the second one is the bytes
# object method
assert(readme.decode().decode() == 'Initial content')

data = {
    'branch': 'master',
    'commit_message': 'blah blah blah',
    'actions': [
        {
            'action': 'create',
            'file_path': 'blah',
            'content': 'blah'
        }
    ]
}
admin_project.commits.create(data)
assert('---' in admin_project.commits.list()[0].diff()[0]['diff'])

# commit status
commit = admin_project.commits.list()[0]
status = commit.statuses.create({'state': 'success', 'sha': commit.id})
assert(len(commit.statuses.list()) == 1)

assert(commit.refs())
assert(commit.merge_requests() is not None)

# commit comment
commit.comments.create({'note': 'This is a commit comment'})
assert(len(commit.comments.list()) == 1)

# commit discussion
count = len(commit.discussions.list())
discussion = commit.discussions.create({'body': 'Discussion body'})
assert(len(commit.discussions.list()) == (count + 1))
d_note = discussion.notes.create({'body': 'first note'})
d_note_from_get = discussion.notes.get(d_note.id)
d_note_from_get.body = 'updated body'
d_note_from_get.save()
discussion = commit.discussions.get(discussion.id)
assert(discussion.attributes['notes'][-1]['body'] == 'updated body')
d_note_from_get.delete()
discussion = commit.discussions.get(discussion.id)
assert(len(discussion.attributes['notes']) == 1)

# housekeeping
admin_project.housekeeping()

# repository
tree = admin_project.repository_tree()
assert(len(tree) != 0)
assert(tree[0]['name'] == 'README.rst')
blob_id = tree[0]['id']
blob = admin_project.repository_raw_blob(blob_id)
assert(blob.decode() == 'Initial content')
archive1 = admin_project.repository_archive()
archive2 = admin_project.repository_archive('master')
assert(archive1 == archive2)
snapshot = admin_project.snapshot()

# project file uploads
filename = "test.txt"
file_contents = "testing contents"
uploaded_file = admin_project.upload(filename, file_contents)
assert(uploaded_file["alt"] == filename)
assert(uploaded_file["url"].startswith("/uploads/"))
assert(uploaded_file["url"].endswith("/" + filename))
assert(uploaded_file["markdown"] == "[{}]({})".format(
    uploaded_file["alt"],
    uploaded_file["url"],
))

# environments
admin_project.environments.create({'name': 'env1', 'external_url':
                                   'http://fake.env/whatever'})
envs = admin_project.environments.list()
assert(len(envs) == 1)
env = envs[0]
env.external_url = 'http://new.env/whatever'
env.save()
env = admin_project.environments.list()[0]
assert(env.external_url == 'http://new.env/whatever')
env.stop()
env.delete()
assert(len(admin_project.environments.list()) == 0)

# project events
admin_project.events.list()

# forks
fork = admin_project.forks.create({'namespace': user1.username})
p = gl.projects.get(fork.id)
assert(p.forked_from_project['id'] == admin_project.id)

# project hooks
hook = admin_project.hooks.create({'url': 'http://hook.url'})
assert(len(admin_project.hooks.list()) == 1)
hook.note_events = True
hook.save()
hook = admin_project.hooks.get(hook.id)
assert(hook.note_events is True)
hook.delete()

# deploy keys
deploy_key = admin_project.keys.create({'title': 'foo@bar', 'key': DEPLOY_KEY})
project_keys = list(admin_project.keys.list())
assert(len(project_keys) == 1)

sudo_project.keys.enable(deploy_key.id)
assert(len(sudo_project.keys.list()) == 1)
sudo_project.keys.delete(deploy_key.id)
assert(len(sudo_project.keys.list()) == 0)

# labels
label1 = admin_project.labels.create({'name': 'label1', 'color': '#778899'})
label1 = admin_project.labels.list()[0]
assert(len(admin_project.labels.list()) == 1)
label1.new_name = 'label1updated'
label1.save()
assert(label1.name == 'label1updated')
label1.subscribe()
assert(label1.subscribed == True)
label1.unsubscribe()
assert(label1.subscribed == False)
label1.delete()

# milestones
m1 = admin_project.milestones.create({'title': 'milestone1'})
assert(len(admin_project.milestones.list()) == 1)
m1.due_date = '2020-01-01T00:00:00Z'
m1.save()
m1.state_event = 'close'
m1.save()
m1 = admin_project.milestones.get(m1.id)
assert(m1.state == 'closed')
assert(len(m1.issues()) == 0)
assert(len(m1.merge_requests()) == 0)

# issues
issue1 = admin_project.issues.create({'title': 'my issue 1',
                                      'milestone_id': m1.id})
issue2 = admin_project.issues.create({'title': 'my issue 2'})
issue3 = admin_project.issues.create({'title': 'my issue 3'})
assert(len(admin_project.issues.list()) == 3)
issue3.state_event = 'close'
issue3.save()
assert(len(admin_project.issues.list(state='closed')) == 1)
assert(len(admin_project.issues.list(state='opened')) == 2)
assert(len(admin_project.issues.list(milestone='milestone1')) == 1)
assert(m1.issues().next().title == 'my issue 1')
note = issue1.notes.create({'body': 'This is an issue note'})
assert(len(issue1.notes.list()) == 1)
emoji = note.awardemojis.create({'name': 'tractor'})
assert(len(note.awardemojis.list()) == 1)
emoji.delete()
assert(len(note.awardemojis.list()) == 0)
note.delete()
assert(len(issue1.notes.list()) == 0)
assert(isinstance(issue1.user_agent_detail(), dict))

assert(issue1.user_agent_detail()['user_agent'])
assert(issue1.participants())

discussion = issue1.discussions.create({'body': 'Discussion body'})
assert(len(issue1.discussions.list()) == 1)
d_note = discussion.notes.create({'body': 'first note'})
d_note_from_get = discussion.notes.get(d_note.id)
d_note_from_get.body = 'updated body'
d_note_from_get.save()
discussion = issue1.discussions.get(discussion.id)
assert(discussion.attributes['notes'][-1]['body'] == 'updated body')
d_note_from_get.delete()
discussion = issue1.discussions.get(discussion.id)
assert(len(discussion.attributes['notes']) == 1)

# tags
tag1 = admin_project.tags.create({'tag_name': 'v1.0', 'ref': 'master'})
assert(len(admin_project.tags.list()) == 1)
tag1.set_release_description('Description 1')
tag1.set_release_description('Description 2')
assert(tag1.release['description'] == 'Description 2')
tag1.delete()

# project snippet
admin_project.snippets_enabled = True
admin_project.save()
snippet = admin_project.snippets.create(
    {'title': 'snip1', 'file_name': 'foo.py', 'code': 'initial content',
     'visibility': gitlab.v4.objects.VISIBILITY_PRIVATE}
)

assert(snippet.user_agent_detail()['user_agent'])

discussion = snippet.discussions.create({'body': 'Discussion body'})
assert(len(snippet.discussions.list()) == 1)
d_note = discussion.notes.create({'body': 'first note'})
d_note_from_get = discussion.notes.get(d_note.id)
d_note_from_get.body = 'updated body'
d_note_from_get.save()
discussion = snippet.discussions.get(discussion.id)
assert(discussion.attributes['notes'][-1]['body'] == 'updated body')
d_note_from_get.delete()
discussion = snippet.discussions.get(discussion.id)
assert(len(discussion.attributes['notes']) == 1)

snippet.file_name = 'bar.py'
snippet.save()
snippet = admin_project.snippets.get(snippet.id)
assert(snippet.content().decode() == 'initial content')
assert(snippet.file_name == 'bar.py')
size = len(admin_project.snippets.list())
snippet.delete()
assert(len(admin_project.snippets.list()) == (size - 1))

# triggers
tr1 = admin_project.triggers.create({'description': 'trigger1'})
assert(len(admin_project.triggers.list()) == 1)
tr1.delete()

# variables
v1 = admin_project.variables.create({'key': 'key1', 'value': 'value1'})
assert(len(admin_project.variables.list()) == 1)
v1.value = 'new_value1'
v1.save()
v1 = admin_project.variables.get(v1.key)
assert(v1.value == 'new_value1')
v1.delete()

# branches and merges
to_merge = admin_project.branches.create({'branch': 'branch1',
                                          'ref': 'master'})
admin_project.files.create({'file_path': 'README2.rst',
                            'branch': 'branch1',
                            'content': 'Initial content',
                            'commit_message': 'New commit in new branch'})
mr = admin_project.mergerequests.create({'source_branch': 'branch1',
                                         'target_branch': 'master',
                                         'title': 'MR readme2'})

# discussion
discussion = mr.discussions.create({'body': 'Discussion body'})
assert(len(mr.discussions.list()) == 1)
d_note = discussion.notes.create({'body': 'first note'})
d_note_from_get = discussion.notes.get(d_note.id)
d_note_from_get.body = 'updated body'
d_note_from_get.save()
discussion = mr.discussions.get(discussion.id)
assert(discussion.attributes['notes'][-1]['body'] == 'updated body')
d_note_from_get.delete()
discussion = mr.discussions.get(discussion.id)
assert(len(discussion.attributes['notes']) == 1)

# basic testing: only make sure that the methods exist
mr.commits()
mr.changes()
assert(mr.participants())

mr.merge()
admin_project.branches.delete('branch1')

try:
    mr.merge()
except gitlab.GitlabMRClosedError:
    pass

# protected branches
p_b = admin_project.protectedbranches.create({'name': '*-stable'})
assert(p_b.name == '*-stable')
p_b = admin_project.protectedbranches.get('*-stable')
# master is protected by default when a branch has been created
assert(len(admin_project.protectedbranches.list()) == 2)
admin_project.protectedbranches.delete('master')
p_b.delete()
assert(len(admin_project.protectedbranches.list()) == 0)

# stars
admin_project.star()
assert(admin_project.star_count == 1)
admin_project.unstar()
assert(admin_project.star_count == 0)

# project boards
#boards = admin_project.boards.list()
#assert(len(boards))
#board = boards[0]
#lists = board.lists.list()
#begin_size = len(lists)
#last_list = lists[-1]
#last_list.position = 0
#last_list.save()
#last_list.delete()
#lists = board.lists.list()
#assert(len(lists) == begin_size - 1)

# project badges
badge_image = 'http://example.com'
badge_link = 'http://example/img.svg'
badge = admin_project.badges.create({'link_url': badge_link, 'image_url': badge_image})
assert(len(admin_project.badges.list()) == 1)
badge.image_url = 'http://another.example.com'
badge.save()
badge = admin_project.badges.get(badge.id)
assert(badge.image_url == 'http://another.example.com')
badge.delete()
assert(len(admin_project.badges.list()) == 0)

# project wiki
wiki_content = 'Wiki page content'
wp = admin_project.wikis.create({'title': 'wikipage', 'content': wiki_content})
assert(len(admin_project.wikis.list()) == 1)
wp = admin_project.wikis.get(wp.slug)
assert(wp.content == wiki_content)
# update and delete seem broken
# wp.content = 'new content'
# wp.save()
# wp.delete()
# assert(len(admin_project.wikis.list()) == 0)

# namespaces
ns = gl.namespaces.list(all=True)
assert(len(ns) != 0)
ns = gl.namespaces.list(search='root', all=True)[0]
assert(ns.kind == 'user')

# features
feat = gl.features.set('foo', 30)
assert(feat.name == 'foo')
assert(len(gl.features.list()) == 1)
feat.delete()
assert(len(gl.features.list()) == 0)

# broadcast messages
msg = gl.broadcastmessages.create({'message': 'this is the message'})
msg.color = '#444444'
msg.save()
msg = gl.broadcastmessages.list(all=True)[0]
assert(msg.color == '#444444')
msg = gl.broadcastmessages.get(1)
assert(msg.color == '#444444')
msg.delete()
assert(len(gl.broadcastmessages.list()) == 0)

# notification settings
settings = gl.notificationsettings.get()
settings.level = gitlab.NOTIFICATION_LEVEL_WATCH
settings.save()
settings = gl.notificationsettings.get()
assert(settings.level == gitlab.NOTIFICATION_LEVEL_WATCH)

# services
service = admin_project.services.get('asana')
service.api_key = 'whatever'
service.save()
service = admin_project.services.get('asana')
assert(service.active == True)
service.delete()
service = admin_project.services.get('asana')
assert(service.active == False)

# snippets
snippets = gl.snippets.list(all=True)
assert(len(snippets) == 0)
snippet = gl.snippets.create({'title': 'snippet1', 'file_name': 'snippet1.py',
                              'content': 'import gitlab'})
snippet = gl.snippets.get(snippet.id)
snippet.title = 'updated_title'
snippet.save()
snippet = gl.snippets.get(snippet.id)
assert(snippet.title == 'updated_title')
content = snippet.content()
assert(content.decode() == 'import gitlab')

assert(snippet.user_agent_detail()['user_agent'])

snippet.delete()
snippets = gl.snippets.list(all=True)
assert(len(snippets) == 0)

# user activities
gl.user_activities.list()

# events
gl.events.list()

# rate limit
settings = gl.settings.get()
settings.throttle_authenticated_api_enabled = True
settings.throttle_authenticated_api_requests_per_period = 1
settings.throttle_authenticated_api_period_in_seconds = 3
settings.save()
projects = list()
for i in range(0, 20):
    projects.append(gl.projects.create(
        {'name': str(i) + "ok"}))

error_message = None
for i in range(20, 40):
    try:
        projects.append(
            gl.projects.create(
                {'name': str(i) + 'shouldfail'}, obey_rate_limit=False))
    except gitlab.GitlabCreateError as e:
        error_message = e.error_message
        break
assert 'Retry later' in error_message.decode()
[current_project.delete() for current_project in projects]
settings.throttle_authenticated_api_enabled = False
settings.save()

# project import/export
ex = admin_project.exports.create({})
ex.refresh()
count = 0
while ex.export_status != 'finished':
    time.sleep(1)
    ex.refresh()
    count += 1
    if count == 10:
        raise Exception('Project export taking too much time')
with open('/tmp/gitlab-export.tgz', 'wb') as f:
    ex.download(streamed=True, action=f.write)

output = gl.projects.import_project(open('/tmp/gitlab-export.tgz', 'rb'),
                               'imported_project')
project_import = gl.projects.get(output['id'], lazy=True).imports.get()
count = 0
while project_import.import_status != 'finished':
    time.sleep(1)
    project_import.refresh()
    count += 1
    if count == 10:
        raise Exception('Project import taking too much time')
