def admin_permission_change(token, u_id, permission_id):
	if permission_id > MEMBER() or permission_id < OWNER():
		raise ValueError(description="Invalid Permission ID")

	registeredUsersDB = get_global_registeredUsers()
	channelsDB = get_global_existingChannels()

	appointerID = token_to_u_ID(registeredUsersDB, token)
	appointerID = int(appointerID)
	u_id = int(u_id)
	permission_id = int(permission_id)
	appointerPID = get_user_permission(appointerID)
	u_PID = get_user_permission(u_id)

	if appointerPID > permission_id:
		raise ValueError(description="You are not permitted to change a user to higher permission!")

	if appointerPID > u_PID:
		raise ValueError(description="You cannot change a permission of a user with higher permission than you")

	registeredUsersDB = get_global_registeredUsers()
	for user in registeredUsersDB:
		if user['u_id'] == u_id:
			user['permission_id'] = permission_id
			promote_to_owner_all_channels(channelsDB, u_id)
			save_registered_users()
			return {}


	raise ValueError(description=f"User with the user id {u_id} not found")
def channel_name_change(token, channel_id, name):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = load_channel()

    check_valid_channel_name(name)
    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in to change the name of a channel!"
        )

    u_id = token_to_u_ID(loggedInUsersDB, token)
    u_id = int(u_id)
    channel_id = int(channel_id)
    if not is_inChannel(
            u_id=u_id, channel_id=channel_id, channelsDB=channelsDB):
        raise AccessError(
            description=
            'You must be in the channel to change the name of a channel!')
    for channel in channelsDB:
        if channel['channel_id'] == channel_id:
            for owner in channel['owner_members']:
                if u_id == owner['u_id']:
                    channel['name'] = name
                    save_channel()
                    return {}
    raise AccessError(
        description=
        'You must be an owner of the channel to change the name of the channel!'
    )
def standup_send(token, channel_id, message):
	registeredUsersDB = get_global_registeredUsers()
	loggedInUsersDB = get_global_loggedInUsers()
	channelsDB = get_global_existingChannels()

	email = token_to_email(token)
	if not is_loggedIn(loggedInUsersDB, email):
		raise AccessError(description="Unauthorised Access")	
	
	channel_id = int(channel_id)
	channel = getChannel(channelsDB, channel_id)
	u_id = token_to_u_ID(loggedInUsersDB, token)

	if not channel['is_standup_running']:
		raise ValueError(description="No standup is running")
	if len(message) > 1000: 
		raise ValueError(description="Message too long")


	if not is_inChannel(channelsDB,channel_id, u_id):
		raise AccessError(description='You must be in a channel to send a standup')


	handle = get_user_handle(registeredUsersDB, u_id)

	message = handle + ' : ' + message +'\n'
	for standup in channel['standups']:
		if standup['isActive']:

			standup['messages'] += message
			
	return {}
def channel_join(token, channel_id):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="you must be logged in to join of a channel!")

    # CHECK THE VALIDITY

    u_id = token_to_u_ID(loggedInUsersDB, token)
    u_id = int(u_id)
    channel_id = int(channel_id)
    first_name = get_firstName(u_id)
    last_name = get_lastName(u_id)
    profile_img_url = get_url(u_id)

    permission = get_user_permission(u_id)
    if permission < MEMBER():
        return join_special(channelsDB, channel_id, u_id, first_name,
                            last_name, profile_img_url)

    else:
        return join_nonSpecial(channelsDB, channel_id, u_id, first_name,
                               last_name, profile_img_url)

    raise ValueError(description="Invalid Channel ID")
def channels_listall(token):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in to view a list of channels!")

    if not channelsDB:
        return {'channels': []}

    u_id = token_to_u_ID(registeredUsersDB, token)
    u_id = int(u_id)
    pID = get_user_permission(u_id)

    channelListDict = []
    for channel in channelsDB:
        if pID < MEMBER():
            channelDict = channel_name_id_dictionary(channel)
            channelListDict.append(channelDict)

        elif channel['is_public']:
            channelDict = channel_name_id_dictionary(channel)
            channelListDict.append(channelDict)

    return {'channels': channelListDict}
def users_all(token):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError("You must be logged in to view all users")
    userList = []
    for user in registeredUsersDB:
        userList.append(user)
    return {'users': userList}
def auth_passwordreset_request(email):
    registeredUsersDB = get_global_registeredUsers()
    for user in registeredUsersDB:
        if email == user['email']:
            reset_code = generate_reset_code()
            reset_code = str(reset_code)
            # set the reset code of the user
            user['reset_code'] = reset_code
            return reset_code
    return None
def auth_passwordreset_reset(code, password):
    registeredUsersDB = get_global_registeredUsers()

    check_valid_reset_code(code)
    check_valid_password(password)

    for user in registeredUsersDB:
        if user['reset_code'] == code:
            user['password'] = hashPassword(password)
            user['reset_code'] = None
            save_registered_users()
            return {}

    raise ValueError(description="Please try again")
def channel_addowner(token, channel_id, u_id):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="you must be logged in to add an owner to a channel!")

    ownerU_ID = token_to_u_ID(loggedInUsersDB, token)
    add_member_to_owner(channelsDB, ownerU_ID, u_id, channel_id)
    save_channel()
    return {}
def user_profile(token, u_id):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)

    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in to view a profile!")

    viewerID = token_to_u_ID(registeredUsersDB, token)

    userDictionary = get_user_profile(registeredUsersDB, u_id)
    save_registered_users()
    return userDictionary
def channel_leave(token, channel_id):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in to leave a channel!")

    u_id = token_to_u_ID(loggedInUsersDB, token)
    u_id = int(u_id)
    channel_id = int(channel_id)
    remove_user_from_channel(channelsDB, u_id, channel_id)
    save_channel()
    return {}
def channels_list(token):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in to view a list of channels!")

    u_id = token_to_u_ID(registeredUsersDB, token)
    if not channelsDB:
        return {'channels': []}

    channelListDict = listUserChannels(channelsDB, u_id)
    return {'channels': channelListDict}
def user_profile_sethandle(token, handle):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in to change your handle")

    check_valid_handle(registeredUsersDB, handle)

    u_id = token_to_u_ID(registeredUsersDB, token)

    update_handle(registeredUsersDB, u_id, handle)
    save_registered_users()
    return {}
def user_profiles_uploadphoto(token, img_url, x_start, y_start, x_end, y_end,
                              base):
    channelsDB = get_global_existingChannels()
    loggedInUsersDB = get_global_loggedInUsers()
    registeredUsersDB = get_global_registeredUsers()

    email = token_to_email(token)
    u_id = token_to_u_ID(registeredUsersDB, token)
    u_id = int(u_id)
    if not base:
        try:
            update_profile_photo(registeredUsersDB, channelsDB, u_id, img_url)
            return update_online_profile_photo(loggedInUsersDB, u_id, img_url)
        except:
            raise AccessError(description="Error uploading the photo")
    base = str(base)
    x_start = int(x_start)
    y_start = int(y_start)
    x_end = int(x_end)
    y_end = int(y_end)

    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError("You must be logged in to change your photo")
    try:
        request.urlopen(img_url)
    except:
        raise ValueError(
            description="Cannot open image URL. Please try other images")

    request.urlretrieve(img_url, f'frontend/prebundle/images/{u_id}.jpg')
    crop_image(f'frontend/prebundle/images/{u_id}.jpg', x_start, y_start,
               x_end,
               y_end).save(f'frontend/prebundle/images/cropped_{u_id}.jpg')
    port = base[-5:-1]
    port = int(port)
    port += 3000
    string = 'http://localhost:' + str(port) + '/'
    local_url = string + f'images/cropped_{u_id}.jpg'  #adding port and http to match the localhost'port'
    print(local_url, '\n\n\n\n\n\n\n\n\n\n\n')
    # UNTIL HERE ONLYhttp://localhost
    # DONT TOUCH THE CODE BELOW
    try:
        update_profile_photo(registeredUsersDB, channelsDB, u_id, local_url)
        return update_online_profile_photo(loggedInUsersDB, u_id, local_url)
    except:
        raise AccessError(description="Error uploading the photo")
def user_setname(token, name_first, name_last):

    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in to change your name!")

    check_valid_name(name_first)
    check_valid_name(name_last)

    u_id = token_to_u_ID(registeredUsersDB, token)

    update_name(registeredUsersDB, channelsDB, u_id, name_first, name_last)
    return {}
def user_profile_delete(token, password):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    password = hashPassword(password)
    email = token_to_email(token)
    u_id = token_to_u_ID(registeredUsersDB, token)
    u_id = int(u_id)

    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError("You must be logged in to delete your account")

    delete_user(registeredUsersDB, u_id, password)
    delete_user(loggedInUsersDB, u_id, password)

    for channel in channelsDB:
        remove_user_from_channel(channelsDB, u_id, channel['channel_id'])

    save_channel()
    save_registered_users()
    return {}
def channel_messages(token, channel_id, start):

    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    start = int(start)
    end = start + PAGINATION()
    channel_id = int(channel_id)
    email = token_to_email(token)

    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description=
            "You must be logged in to view the messages of a channel!")

    u_id = token_to_u_ID(loggedInUsersDB, token)
    channel = getChannel(channelsDB, channel_id)
    messagesLength = len(channel['messagesListDict'])

    if messagesLength < start:
        raise ValueError(description="Starting message too big")

    returnDictionary = {'messages': []}

    if messagesLength < end:
        returnDictionary['end'] = -1
        returnDictionary['start'] = start
    else:
        returnDictionary['end'] = end
        returnDictionary['start'] = start

    for message in channel['messagesListDict']:
        if start == end:
            break
        returnDictionary['messages'].append(message)
        start += 1
    save_channel()
    return returnDictionary
def standup_start(token, channel_id, length):
	registeredUsersDB = get_global_registeredUsers()
	loggedInUsersDB = get_global_loggedInUsers()
	channelsDB = get_global_existingChannels()
	
	email = token_to_email(token)
	if not is_loggedIn(loggedInUsersDB, email):
		raise AccessError(description="You should be logged in to start a standup")	
	
	channel_id = int(channel_id)
	channel = getChannel(channelsDB, channel_id)
	u_id = token_to_u_ID(loggedInUsersDB, token)

	if channel['is_standup_running']:
		raise ValueError("Another standup is currently running")
	
	# Only owner of the channel can start a standup
	found = False
	for owner in channel['owner_members']:
		if owner['u_id'] == u_id:
			found = True
	if not found:
		raise AccessError(description='You must be an owner of a channel to start a standup')

	now = datetime.datetime.utcnow()
	time_start = int(now.replace(tzinfo=timezone.utc).timestamp())
	time_end = int(time_start + int(length)) 
	
	tempDict = {}
	tempDict['u_id'] = u_id
	tempDict['isActive'] = True
	tempDict['time_start'] = time_start
	tempDict['time_end'] = time_end
	tempDict['messages'] = ''
	channel['is_standup_running'] = True
	channel['standups'].append(tempDict)

	return {'time_finish': time_end}
def standup_active(token, channel_id):
	registeredUsersDB = get_global_registeredUsers()
	loggedInUsersDB = get_global_loggedInUsers()
	channelsDB = get_global_existingChannels()

	email = token_to_email(token)
	if not is_loggedIn(loggedInUsersDB, email):
		raise AccessError(description="You must be logged in to see if a standup is active!")	
	
	channel_id = int(channel_id)
	channel = getChannel(channelsDB, channel_id)
	u_id = token_to_u_ID(loggedInUsersDB, token)

	if not channel['is_standup_running']:
		for standup in channel['standups']:
			standup['isActive'] = False
		return {'is_active':False, 'time_finish': None}

	for standup in channel['standups']:
		if standup['isActive']:
			return {'is_active':True, 'time_finish': standup['time_end']}

	channel['is_standup_running'] = False
	save_channel()
def channel_invite(token, channel_id, u_id):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()

    email = token_to_email(token)
    u_id = int(u_id)

    if not is_loggedIn(loggedInUsersDB, email):
        raise AccessError(
            description="You must be logged in invite a friend into a channel!"
        )

    if not is_already_registered(registeredUsersDB, email):
        raise ValueError(description=f"User with ID {u_id} does not exist")

    ownerU_ID = token_to_u_ID(loggedInUsersDB, token)

    ownerU_ID = int(ownerU_ID)
    channel_id = int(channel_id)

    add_to_channel(channelsDB, ownerU_ID, u_id, channel_id)
    save_channel()
    return {}
def channels_create(token, name, is_public):
    registeredUsersDB = get_global_registeredUsers()
    loggedInUsersDB = get_global_loggedInUsers()
    channelsDB = get_global_existingChannels()
    email = token_to_email(token)

    if not is_loggedIn(loggedInUsersDB, email):

        raise AccessError(
            description="You must be logged in to create a channel!")

    is_public = true_or_false(is_public)

    check_valid_channel_name(name)

    u_id = token_to_u_ID(loggedInUsersDB, token)
    u_id = int(u_id)

    channel_id = generateChannelID(channelsDB, name, u_id)

    first_name = get_firstName(u_id)
    last_name = get_lastName(u_id)
    url = get_url(u_id)

    channelDict = create_channel_details(name=name,
                                         channel_id=channel_id,
                                         is_public=is_public,
                                         u_id=u_id,
                                         name_first=first_name,
                                         name_last=last_name,
                                         profile_img_url=url)
    channelsDB.append(channelDict)

    save_channel()

    return {'channel_id': channel_id}
def get_user_permission(u_id):
    registeredUsers = get_global_registeredUsers()
    for user in registeredUsers:
        if user['u_id'] == u_id:
            return user['permission_id']
def get_url(u_id):
    registeredUsersDB = get_global_registeredUsers()
    for user in registeredUsersDB:
        if user['u_id'] == u_id:
            return user['profile_img_url']
def get_firstName(u_id):
    registeredUsersDB = get_global_registeredUsers()
    for user in registeredUsersDB:
        if user['u_id'] == u_id:
            return user['name_first']