use crate::{unwrap, File};
use rusty_yaml::Yaml;
use std::fmt::{Display, Error, Formatter};
use std::process::exit;
pub enum VersionControlSystem {
    GitHub,
    Unsupported,
}
pub const AUTH_TOKEN_PATH: &str = "auth.token";
pub struct MergeRequestHandler {
                            vcs: VersionControlSystem,
        owner: String,
                repo_name: String,
                                    whitelist: Vec<String>,
        auth_token: String,
            repository_type: String,
}
impl MergeRequestHandler {
    pub fn new(
        vcs: VersionControlSystem,
        owner: String,
        repo_name: String,
        whitelist: Vec<String>,
    ) -> Self {
        let auth_token = match File::read(AUTH_TOKEN_PATH) {
            Ok(s) => s.trim().to_string(),
            Err(e) => {
                error!(
                    "Could not read authentication token from file '{}' because {}",
                    AUTH_TOKEN_PATH, e
                );
                exit(1);
            }
        };
        if auth_token.len() == 0 {
            error!(
                "You didn't write your VCS's authentication token to '{}'!",
                AUTH_TOKEN_PATH
            );
            exit(0);
        }
        Self {
            vcs,
            owner,
            repo_name,
            whitelist,
            auth_token,
            repository_type: String::from("git"),         }
    }
}
impl Display for MergeRequestHandler {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match &self.vcs {
            VersionControlSystem::GitHub => write!(
                f,
                "whitelist_authors = {:?}
try:
    c['change_source'].append(changes.GitHubPullrequestPoller(
            owner=\"{owner}\",
            repo=\"{name}\",
            # right now just poll every 60 seconds
            # this will need to change in the future, but this is just for testing.
            pollInterval=120,
            repository_type=\"{repository_type}\",
            github_property_whitelist=[\"*\"],
            token=\"{token}\"))
except Exception as e:
    print(f\"Could not create merge request handler: {{str(e)}}\")
context = util.Interpolate(\"%(prop:buildername)s\")
github_status_service = reporters.GitHubStatusPush(token='{token}',
                                context=context,
                                startDescription='Build started.',
                                endDescription='Build done.')
c['services'].append(github_status_service)
def is_whitelisted(props, password):
    for prop in ['github.number', 'github.comments_url', 'github.user.login']:
        # If these properties arent present, its not a pull request
        if not (props.hasProperty(prop)):
            return True
    
    # URL for comments info
    comments_url = props['github.comments_url']
    # The pull request number that we'll try to whitelist
    pr_number = props['github.number']
    # The author of the PR
    author = props['github.user.login']
    resp = req.get(comments_url)
    try:
        # Try to convert to a JSON object so we can read the data
        json_acceptable_string = resp.text.replace(\"'\", \"\\\"\")
        comments_json = json.loads(json_acceptable_string)
        # Check each comment
        for comment in comments_json:
            # If the comment was made by an admin and matches the password
            if comment['user']['login'] in whitelist_authors and re.fullmatch(password, comment['body']):
                # If the pull request was not already in the whitelisted PRs, add it
                print(\"ADMIN: \" + str(comment['user']['login']) + \" PASSWORD: \" + str(comment['body']))
                print(f\"PR NUMBER {{pr_number}} IS GOOD TO TEST\")
                return True
    except Exception as e:
        # There was a problem converting to JSON, github returned bad data
        print(f\"There was an error: {{str(e)}}. If this error has anything to do with JSON, its likely that you've queried GitHub too many times.\")
        # Write the returned webpage to BAD
        open('BAD', 'w').write(resp.text)
    
    if author in whitelist_authors:
        print(\"WHITELISTED AUTHOR\")
        return True
    return False
",
                self.whitelist,
                token = self.auth_token.trim_matches('"'),
                name = self.repo_name.trim_matches('"'),
                owner = self.owner.trim_matches('"'),
                repository_type = self.repository_type.trim_matches('"'),
            ),
            VersionControlSystem::Unsupported => write!(
                f,
                "print('We currently dont support building merge requests on your VCS.')"
            ),
        }
    }
}
impl From<Yaml> for MergeRequestHandler {
    fn from(yaml: Yaml) -> Self {
                for section in ["version-control-system", "owner", "repo-name", "whitelist"].iter() {
            if !yaml.has_section(section) {
                error!("There was an error creating the merge request handler: '{}' section not specified", section);
                exit(1);
            }
        }
        
        let vcs: VersionControlSystem = match unwrap(&yaml, "version-control-system").as_str() {
            "github" => VersionControlSystem::GitHub,
            _ => {
                warn!(
                    "We do not support building merge requests on your version control system yet!"
                );
                warn!(
                    "We will proceed with the build. All other features should function as intended."
                );
                VersionControlSystem::Unsupported
            }
        };
                let owner: String = unwrap(&yaml, "owner");
                let repo_name: String = unwrap(&yaml, "repo-name");
                        let mut whitelist: Vec<String> = vec![];
        for author in yaml.get_section("whitelist").unwrap() {
            whitelist.push(
                author
                    .to_string()
                    .trim_matches('"')
                    .trim_matches('\'')
                    .to_string(),
            );
        }
                Self::new(vcs, owner, repo_name, whitelist)
    }
}