<?php

namespace IPS\Login;

class _Vkontakte extends LoginAbstract
{
	/** 
	 * @brief	Icon
	 */
	public static $icon = 'vk';
	
	/**
	 * Get Form
	 *
	 * @param	\IPS\Http\Url	$url	The URL for the login page
	 * @return	string
	 */
	public function loginForm( $url, $ucp=FALSE )
	{
		$url = \IPS\Http\Url::internal( 'applications/core/interface/vkontakte/auth.php', 'none' );
		
		if ( $ucp )
		{
			$state = "ucp-" . \IPS\Session::i()->csrfKey;
		}
		else
		{
			$state = \IPS\Dispatcher::i()->controllerLocation . "-" . \IPS\Session::i()->csrfKey;
		}

		return \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->vkontakte( "https://oauth.vk.com/authorize?client_id={$this->settings['app_id']}&amp;scope=email&amp;redirect_uri=".urlencode( $url ) . "&amp;state={$state}&amp;response_type=code"  );
		
	}
	
	/**
	 * Authenticate
	 *
	 * @param	string			$url	The URL for the login page
	 * @param	\IPS\Member		$member	If we want to integrate this login method with an existing member, provide the member object
	 * @return	\IPS\Member
	 * @throws	\IPS\Login\Exception
	 */
	public function authenticate( $url, $member=NULL )
	{
		$url = $url->setQueryString( 'loginProcess', 'vkontakte' );
		
		try
		{
			
			/* Get a token */
			try
			{
				$response = \IPS\Http\Url::external( "https://oauth.vk.com/access_token?client_id={$this->settings['app_id']}&redirect_uri=".(string) \IPS\Http\Url::internal( 'applications/core/interface/vkontakte/auth.php', 'none' )."&client_secret={$this->settings['app_secret']}&code=".\IPS\Request::i()->code 
					)->request()->get()->decodeJson();
			}
			catch( \RuntimeException $e )
			{
				throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
			}
			
			/* Get the user data */
			$userData = $response;
			if(!isset($userData['email'])) throw new \IPS\Login\Exception( 'В вашем аккаунте ВК отсутствует email, укажите его!', \IPS\Login\Exception::INTERNAL_ERROR );
   			/* Find or create member */
   			$newMember = FALSE;
   			if ( $member === NULL )
   			{
				$member = \IPS\Member::load( $userData['email'], 'email' );
				if ( !$member->member_id )
				{
					
					$member = new \IPS\Member;
					if ( \IPS\Settings::i()->reg_auth_type == 'admin' or \IPS\Settings::i()->reg_auth_type == 'admin_user' )
					{
						$member->members_bitoptions['validating'] = TRUE;
					}
					$member->member_group_id = \IPS\Settings::i()->member_group;
					$member->email = $userData['email'];
					$member->profilesync = json_encode( array( 'vkontakte' => array( 'photo' => TRUE, 'cover' => FALSE, 'status' => TRUE ) ) );
					$newMember = TRUE;

					$name1 = \IPS\Http\Url::external( "https://api.vk.com/method/users.get?user_id={$userData['user_id']}&v=5.29&access_token={$response['access_token']}&fields=first_name,last_name,screen_name,bdate,nickname" )->request()->get()->decodeJson();
					
					$member->name = $name1['response'][0]['nickname'];

					if ( empty($member->name) AND $this->settings['real_name'] )
					{
						$name = $name1['response'][0]['first_name'].' '.$name1['response'][0]['last_name'];
						$existingUsername = \IPS\Member::load( $name, 'name' );
						
						if ( !$existingUsername->member_id )
						{
							$member->name = $name;
						}
					}

					
					
				}
			}

			$member->vk_uid = $userData['user_id'];
			$member->vk_token = $response['access_token'];
			$member->save();

			/* Sync */
			if ( $newMember )
			{
				if ( \IPS\Settings::i()->reg_auth_type == 'admin_user' )
				{
					\IPS\Db::i()->update( 'core_validating', array( 'user_verified' => 1 ), array( 'member_id=?', $member->member_id ) );
				}

				$sync = new \IPS\core\ProfileSync\VK( $member );
				
				$sync->sync();
			}
			
			/* Return */
			return $member;
   		}
   		catch ( \IPS\Http\Request\Exception $e )
   		{
	   		throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
   		}
	}
	
	public static function link( \IPS\Member $member, $details )
	{
		try {
		$userData = \IPS\Http\Url::external( "https://api.vk.com/method/users.get?uid={$details[1]}&access_token={$details[0]}&fields=first_name,last_name,screen_name,bdate,nickname" )->request()->get()->decodeJson();
		$userData = $userData['response'][0];
		$member->vk_id = $details[1];
		$member->vk_token = $details[0];
		$member->save();
		}catch(\Exception $e) {}
	}
	
	/**
	 * ACP Settings Form
	 *
	 * @param	string	$url	URL to redirect user to after successful submission
	 * @return	array	List of settings to save - settings will be stored to core_login_handlers.login_settings DB field
	 * @code
	 	return array( 'savekey'	=> new \IPS\Helpers\Form\[Type]( ... ), ... );
	 * @endcode
	 */
	public function acpForm()
	{
		$where	= array( array( 'template_group=?', 'login' ) );

				$where[]	= array( 'template_app=?', 'core' );

				$where[]	= array( 'template_location=?', 'global' );

			$results	= array();
			$selects = \IPS\Db::i()->select( 'template_name', 'core_theme_templates', $where );
			$selects->rewind();
			while($selects->valid())
			{
				$results[ $selects->current() ]	= $selects->current();
				$selects->next();
			}
		
			$results = array_unique( $results );
		//if(\IPS\IN_DEV) {

			if(!in_array('vkontakte',$results)) {

				ob_start();?>
<ips:template parameters="$url" />
<a href='{$url}' class='ipsButton ipsButton_verySmall ipsButton_fullWidth ipsSocial ipsSocial_vk' style="background-color:#56789C;">
	<span class='ipsSocial_icon'><i class='fa fa-vk'></i></span>
	<span class='ipsSocial_text'>{lang="login_vkontakte"}</span>
</a>
				<?
				$html   = ob_get_contents();
				ob_end_clean();
				$params = array();
				
				/* Parse the header tag */
				preg_match( '/^<ips:template parameters="(.+?)?" \/>\n/', $html, $params );
				
				/* Strip it */
				$html = ( isset($params[0]) ) ? str_replace( $params[0], '', $html ) : $html;
				$id=0;
				\IPS\Db::i()->insert( 'core_theme_templates', array( 'template_set_id'     => $id,
																					 'template_app'		   => 'core',
																					 'template_added_to'   => $id,
																					 'template_location'   => 'global',
																					 'template_group'      => 'login',
																					 'template_name'	   => 'vkontakte',
																					 'template_data'	   => ( isset( $params[1] ) ) ? $params[1] : '',
																					 'template_content'    => $html,
																					 'template_updated'    => time(),
																					 'template_unique_key' => md5( $id . ';' . 'core' . ';' . 'global' . ';' . 'login' . ';' . ( 'vkontakte' ) ),
																					 'template_removable'  => $id ) );
				\IPS\Theme::load( \IPS\Theme::i()->defaultTheme() )->compileTemplates( 'core' );
				
			}
			
		/*}elseif(!in_array('vkontakte',$results)) {

			\IPS\Output::i()->sidebar['actions'] = array(
			'help'	=> array(
				'link'		=> \IPS\Http\Url::internal( '&app=core&module=settings&controller=login&do=form&id=vkontakte' ),
				'title'		=> 'Шаблоны не синхронизированы. Включите DEV-режим и перезагрузите страницу!',
			),
		);
		}*/

		return array(
			'app_id'		=> new \IPS\Helpers\Form\Text( 'login_vkontakte_app', ( isset( $this->settings['app_id'] ) ) ? $this->settings['app_id'] : '', TRUE ),
			'app_secret'	=> new \IPS\Helpers\Form\Text( 'login_vkontakte_secret', ( isset( $this->settings['app_secret'] ) ) ? $this->settings['app_secret'] : '', TRUE ),
			'real_name'		=> new \IPS\Helpers\Form\YesNo( 'login_real_name', ( isset( $this->settings['real_name'] ) ) ? $this->settings['real_name'] : FALSE, TRUE )
		);
	}
	
	/**
	 * Test Settings
	 *
	 * @return	bool
	 * @throws	\InvalidArgumentException
	 */
	public function testSettings()
	{
		return TRUE;
	}
	
	/**
	 * Can a member sign in with this login handler?
	 * Used to ensure when a user disassociates a social login that they have some other way of logging in
	 *
	 * @param	\IPS\Member	$member	The member
	 * @return	bool
	 */
	public function canProcess( \IPS\Member $member )
	{
		return ( $member->vk_id and $member->vk_token );
	}
	
	/**
	 * Can a member change their email/password with this login handler?
	 *
	 * @param	string		$type	'email' or 'password'
	 * @param	\IPS\Member	$member	The member
	 * @return	bool
	 */
	public function canChange( $type, \IPS\Member $member )
	{
		return FALSE;
	}
}