<?php

defined( 'ABSPATH' ) || exit;

class Play_Follow {

    protected static $_instance = null;

    private $user_id;
    private $meta_key_follow = 'follow';
    private $meta_key_following = 'following';

    public static function instance() {
        if ( is_null( self::$_instance ) ) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    /**
     * Initialize the actions.
     */
    public function __construct() {
        add_action( 'the_follow_button', array( $this, 'the_follow_button' ), 10, 2 );
        add_action( 'play_follow', array( $this, 'follow' ), 10 );

        add_filter( 'user_follow', array( $this, 'get_follow' ), 10, 3 );
        add_filter( 'user_following', array( $this, 'get_following' ), 10, 2 );
        do_action( 'play_block_follow_init', $this );
    }

    /**
     * follow
     */
    public function follow( $request ) {
        $this->user_id = get_current_user_id();

        $user_id = (int) $request[ 'id' ];

        if ( ! is_user_logged_in() ) {
            Play_Utils::instance()->response( array(
                'error' => 'You need to login',
                'url'   => wp_login_url( get_author_posts_url( $user_id ) )
            ) );
        }

        if ( Play_Utils::instance()->validate_nonce( $request['nonce'] ) ) {
            if ( $this->is_current_user_following( $user_id ) ) {
                $this->remove_follow( $user_id );
                $status = 0;
                do_action( 'play_block_unfollow_after_save', $user_id, $this->user_id );
            } else {
                $this->add_follow( $user_id );
                $status = 1;
                do_action( 'play_block_follow_after_save', $user_id, $this->user_id );
            }

            Play_Utils::instance()->response( array(
                'status' => $status,
                'count'  => Play_Utils::instance()->format_count( count( $this->get_follow( $user_id ) ) )
            ) );
        }
    }

    /**
     * Add a follow
     */
    public function add_follow( $user_id ) {
        // add to user meta
        $follow = $this->get_follow( $user_id );
        if ( ! in_array( $this->user_id, $follow ) ) {
            $follow[] = $this->user_id;
            update_user_meta( $user_id, $this->meta_key_follow, $follow );
        }

        // add and update to current user meta
        $following = $this->get_following( $this->user_id );
        if ( ! in_array( $user_id, $following ) ) {
            $following[] = $user_id;
            update_user_meta( $this->user_id, $this->meta_key_following, $following );
        }

        return apply_filters( 'play_add_follow', $following, $user_id, $this );
    }

    /**
     * Remove a follow
     */
    public function remove_follow( $user_id ) {
        // remove from user meta
        $follow = $this->get_follow( $user_id );

        if ( in_array( $this->user_id, $follow ) ) {
            foreach ( $follow as $k => $id ) {
                if ( $id == $this->user_id ) {
                    unset( $follow[ $k ] );
                }
            }
            update_user_meta( $user_id, $this->meta_key_follow, $follow );
        }

        // remove and update to current user meta
        $following = $this->get_following( $this->user_id );
        if ( in_array( $user_id, $following ) ) {
            foreach ( $following as $k => $id ) {
                if ( $id == $user_id ) {
                    unset( $following[ $k ] );
                }
            }
            update_user_meta( $this->user_id, $this->meta_key_following, $following );
        }

        return apply_filters( 'play_remove_follow', $following, $user_id, $this );
    }

    /**
     * Check if a user following
     */
    public function is_current_user_following( $user_id ) {
        $ids = $this->get_following( $this->user_id );
        if ( in_array( $user_id, $ids ) ) {
            return true;
        }

        return false;
    }

    /**
     * Get following
     */
    public function get_following( $user_id = null, $formated = false, $show_empty = false ) {
        $user_id = ( isset( $user_id ) ) ? $user_id : get_current_user_id();
        $users   = get_user_meta( $user_id, $this->meta_key_following, true );
        if ( $users == '' && $show_empty ) {
            return '0';
        }
        if ( $users == '' ) {
            $users = array();
        }

        $users = apply_filters( 'play_get_following', $users, $user_id, $formated, $show_empty, $this );

        return $formated ? Play_Utils::instance()->format_count( count( $users ) ) : $users;
    }

    /**
     * Get follow
     */
    public function get_follow( $user_id = null, $formated = false, $show_empty = false ) {
        $user_id = ( isset( $user_id ) ) ? $user_id : get_current_user_id();
        $users   = get_user_meta( $user_id, $this->meta_key_follow, true );
        if ( ( $users == '' || empty( $users ) ) && $show_empty ) {
            return '0';
        }
        if ( $users == '' ) {
            $users = array();
        }

        return $formated ? Play_Utils::instance()->format_count( count( $users ) ) : $users;
    }

    /**
     * Remove invalid
     */
    public function remove_invalid( $ids ) {
        foreach ( $ids as $key => $id ) {
            if ( ! $this->user_exists( $id ) ) {
                unset( $ids[ $key ] );
            }
        }

        return $ids;
    }

    /**
     * User exists
     */
    public function user_exists( $id ) {
        global $wpdb;
        $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->users WHERE ID = %d", $id ) );
        if ( $count == 1 ) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Display follow button
     */
    public function the_follow_button( $user_id, $class = '' ) {
        if ( $user_id == get_current_user_id() || !get_option( 'users_can_register' ) ) {
            return;
        }
        echo $this->get_follow_button( $user_id, $class );
    }

    /**
     * Get follow button
     */
    public function get_follow_button( $user_id, $class = '' ) {
        $following = $this->is_current_user_following( $user_id );
        $button       = sprintf( '<button class="btn-follow button-primary %s %s" data-id="%d" data-action="follow" data-type="users">%s</button>', esc_attr( $class ), $following ? ' active' : '', (int) $user_id, Play_Utils::instance()->get_template_html( 'blocks/follow.php' ) );

        return apply_filters( 'play_follow_button', $button, $user_id );
    }

}

Play_Follow::instance();
