<?php
namespace App\Http\Controllers;

use App\Helpers\Helper;
use App\Http\Requests\AssetFileRequest;
use App\Http\Requests\SaveUserRequest;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Group;
use App\Models\Ldap;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\WelcomeNotification;
use Artisan;
use Auth;
use Config;
use Crypt;
use DB;
use Gate;
use HTML;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Input;
use Lang;
use League\Csv\Reader;
use Mail;
use Redirect;
use Response;
use Str;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use URL;
use View;

/**
 * This controller handles all actions related to Users for
 * the Snipe-IT Asset Management application.
 *
 * @version    v1.0
 */


class UsersController extends Controller
{


    /**
    * Returns a view that invokes the ajax tables which actually contains
    * the content for the users listing, which is generated in getDatatable().
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @see UsersController::getDatatable() method that generates the JSON response
    * @since [v1.0]
    * @return \Illuminate\Contracts\View\View
     */
    public function index()
    {
        $this->authorize('index', User::class);
        return view('users/index');
    }

    /**
    * Returns a view that displays the user creation form.
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @return \Illuminate\Contracts\View\View
     */
    public function create()
    {
        $this->authorize('create', User::class);
        $groups = Group::pluck('name', 'id');

        if (Input::old('groups')) {
            $userGroups = Group::whereIn('id', Input::old('groups'))->pluck('name', 'id');
        } else {
            $userGroups = collect();
        }

        $permissions = config('permissions');
        $userPermissions = Helper::selectedPermissionsArray($permissions, Input::old('permissions', array()));
        $permissions = $this->filterDisplayable($permissions);

        $user = new User;
        $user->activated = 1;

        return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions'))
        ->with('user', $user);
    }

    /**
    * Validate and store the new user data, or return an error.
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @return \Illuminate\Http\RedirectResponse
     */
    public function store(SaveUserRequest $request)
    {
        $this->authorize('create', User::class);
        $user = new User;
        //Username, email, and password need to be handled specially because the need to respect config values on an edit.
        $user->email = $data['email'] = e($request->input('email'));
        $user->username = $data['username'] = e($request->input('username'));
        if ($request->filled('password')) {
            $user->password = bcrypt($request->input('password'));
            $data['password'] =  $request->input('password');
        }
        $user->first_name = $request->input('first_name');
        $user->last_name = $request->input('last_name');
        $user->locale = $request->input('locale');
        $user->employee_num = $request->input('employee_num');
        $user->activated = $request->input('activated', 0);
        $user->jobtitle = $request->input('jobtitle');
        $user->phone = $request->input('phone');
        $user->location_id = $request->input('location_id', null);
        $user->department_id = $request->input('department_id', null);
        $user->company_id = Company::getIdForUser($request->input('company_id', null));
        $user->manager_id = $request->input('manager_id', null);
        $user->notes = $request->input('notes');
        $user->address = $request->input('address', null);
        $user->city = $request->input('city', null);
        $user->state = $request->input('state', null);
        $user->country = $request->input('country', null);
        $user->zip = $request->input('zip', null);

        // Strip out the superuser permission if the user isn't a superadmin
        $permissions_array = $request->input('permission');

        if (!Auth::user()->isSuperUser()) {
            unset($permissions_array['superuser']);
        }
        $user->permissions =  json_encode($permissions_array);

        if ($user->save()) {

            if ($request->filled('groups')) {
                $user->groups()->sync($request->input('groups'));
            } else {
                $user->groups()->sync(array());
            }

            if (($request->input('email_user') == 1) && ($request->filled('email'))) {
              // Send the credentials through email
                $data = array();
                $data['email'] = e($request->input('email'));
                $data['username'] = e($request->input('username'));
                $data['first_name'] = e($request->input('first_name'));
                $data['last_name'] = e($request->input('last_name'));
                $data['password'] = e($request->input('password'));

                $user->notify(new WelcomeNotification($data));

/*                Mail::send('emails.send-login', $data, function ($m) use ($user) {
                    $m->to($user->email, $user->first_name . ' ' . $user->last_name);
                    $m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
                    $m->subject(trans('mail.welcome', ['name' => $user->first_name]));
                });*/
            }
            return redirect::route('users.index')->with('success', trans('admin/users/message.success.create'));
        }
        return redirect()->back()->withInput()->withErrors($user->getErrors());
    }



    private function filterDisplayable($permissions)
    {
        $output = null;
        foreach ($permissions as $key => $permission) {
                $output[$key] = array_filter($permission, function ($p) {
                    return $p['display'] === true;
                });
        }
        return $output;
    }

    /**
     * Returns a view that displays the edit user form
     *
     * @author [A. Gianotto] [<snipe@snipe.net>]
     * @since [v1.0]
     * @param $permissions
     * @return View
     * @internal param int $id
     */
    public function edit($id)
    {

        if ($user =  User::find($id)) {

            $this->authorize('update', $user);
            $permissions = config('permissions');

            $groups = Group::pluck('name', 'id');

            $userGroups = $user->groups()->pluck('name', 'id');
            $user->permissions = $user->decodePermissions();
            $userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions);
            $permissions = $this->filterDisplayable($permissions);

            return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))->with('item', $user);
        }

        $error = trans('admin/users/message.user_not_found', compact('id'));
        return redirect()->route('users.index')->with('error', $error);


    }

    /**
     * Validate and save edited user data from edit form.
     *
     * @author [A. Gianotto] [<snipe@snipe.net>]
     * @since [v1.0]
     * @param UpdateUserRequest $request
     * @param  int $id
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(SaveUserRequest $request, $id = null)
    {
        // We need to reverse the UI specific logic for our
        // permissions here before we update the user.
        $permissions = $request->input('permissions', array());
        app('request')->request->set('permissions', $permissions);
        // Only update the email address if locking is set to false
        if (config('app.lock_passwords')) {
            return redirect()->route('users.index')->with('error', 'Denied! You cannot update user information on the demo.');
        }

        try {

            $user = User::find($id);

            if ($user->id == $request->input('manager_id')) {
                return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.');
            }

            // If the user isn't a superuser, don't let them edit their own permissions
            if ((!Auth::user()->isSuperUser()) && ($user->id == Auth::user()->id)) {
                return redirect()->back()->withInput()->with('error', 'You cannot edit your own permissions. Please contact an administrator.');
            }

            $this->authorize('update', $user);
            // Figure out of this user was an admin before this edit
            $orig_permissions_array = $user->decodePermissions();
            $orig_superuser = '0';
            if (is_array($orig_permissions_array)) {
                if (array_key_exists('superuser', $orig_permissions_array)) {
                    $orig_superuser = $orig_permissions_array['superuser'];
                }
            }


        } catch (ModelNotFoundException $e) {
            return redirect()->route('users.index')
                ->with('error', trans('admin/users/message.user_not_found', compact('id')));
        }


        // Only save groups if the user is a super user
        if (Auth::user()->isSuperUser()) {
            $user->groups()->sync($request->input('groups'));
        }


        if ($request->filled('username')) {
            $user->username = $request->input('username');
        }
        $user->email = $request->input('email');


       // Update the user
        $user->first_name = $request->input('first_name');
        $user->last_name = $request->input('last_name');
        $user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
        $user->locale = $request->input('locale');
        $user->employee_num = $request->input('employee_num');
        $user->activated = $request->input('activated', 0);
        $user->jobtitle = $request->input('jobtitle', null);
        $user->phone = $request->input('phone');
        $user->website = $request->input('website', null);
        $user->location_id = $request->input('location_id', null);
        $user->company_id = Company::getIdForUser($request->input('company_id', null));
        $user->manager_id = $request->input('manager_id', null);
        $user->notes = $request->input('notes');
        $user->department_id = $request->input('department_id', null);
        $user->address = $request->input('address', null);
        $user->city = $request->input('city', null);
        $user->state = $request->input('state', null);
        $user->country = $request->input('country', null);
        $user->activated = $request->input('activated', 0);
        $user->zip = $request->input('zip', null);


        // Update the location of any assets checked out to this user
        Asset::where('assigned_type', User::class)
            ->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);

        // Do we want to update the user password?
        if ($request->filled('password')) {
            $user->password = bcrypt($request->input('password'));
        }

        // Strip out the superuser permission if the user isn't a superadmin
        $permissions_array = $request->input('permission');

        if (!Auth::user()->isSuperUser()) {
            unset($permissions_array['superuser']);
            $permissions_array['superuser'] = $orig_superuser;
        }

        $user->permissions =  json_encode($permissions_array);

        // Was the user updated?
        if ($user->save()) {
            // Prepare the success message
            $success = trans('admin/users/message.success.update');
            // Redirect to the user page
            return redirect()->route('users.index')->with('success', $success);
        }
        return redirect()->back()->withInput()->withErrors($user->getErrors());
    }

    /**
    * Delete a user
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @param  int  $id
    * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($id = null)
    {
        try {
            // Get user information
            $user = User::findOrFail($id);
            // Authorize takes care of many of our logic checks now.
            $this->authorize('delete', User::class);

            // Check if we are not trying to delete ourselves
            if ($user->id === Auth::user()->id) {
                // Redirect to the user management page
                return redirect()->route('users.index')->with('error', 'You cannot delete yourself.');
            }

            if (($user->assets) && ($user->assets->count() > 0)) {
                // Redirect to the user management page
                return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets->count() . ' assets associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
            }

            if (($user->licenses) && ($user->licenses->count() > 0)) {
                // Redirect to the user management page
                return redirect()->route('users.index')->with('error', 'This user still has ' . $user->licenses->count() . ' license(s associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
            }

            if (($user->accessories) && ($user->accessories->count() > 0)) {
                // Redirect to the user management page
                return redirect()->route('users.index')->with('error', 'This user still has ' . $user->accessories->count() . ' accessories associated with them. Use the Checkin and Delete button on the user profile to check these items back in and delete this user.');
            }

            if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
                // Redirect to the user management page
                return redirect()->route('users.index')->with('error', 'This user still has ' . $user->managedLocations()->count() . ' locations that they manage.');
            }

            // Delete the user
            $user->delete();

            // Prepare the success message
            $success = trans('admin/users/message.success.delete');

            // Redirect to the user management page
            return redirect()->route('users.index')->with('success', $success);
        } catch (ModelNotFoundException $e) {
            // Prepare the error message
            $error = trans('admin/users/message.user_not_found', compact('id'));
            // Redirect to the user management page
            return redirect()->route('users.index')->with('error', $error);
        }
    }

    /**
    * Returns a view that confirms the user's a bulk delete will be applied to.
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.7]
    * @return \Illuminate\Contracts\View\View
     */
    public function postBulkEdit(Request $request)
    {
        $this->authorize('update', User::class);

        if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
            $statuslabel_list = Helper::statusLabelList();
            $user_raw_array = array_keys(Input::get('ids'));
            $users = User::whereIn('id', $user_raw_array)->with('groups', 'assets', 'licenses', 'accessories')->get();
            if ($request->input('bulk_actions') == 'edit') {
                return view('users/bulk-edit', compact('users'))
                    ->with('groups', Group::pluck('name', 'id'));
            }
            return view('users/confirm-bulk-delete', compact('users', 'statuslabel_list'));
        }

        return redirect()->back()->with('error', 'No users selected');
    }


    /**
     * Save bulk-edited users
     *
     * @author [A. Gianotto] [<snipe@snipe.net>]
     * @since [v1.0]
     * @return \Illuminate\Http\RedirectResponse
     */
    public function postBulkEditSave(Request $request)
    {
        $this->authorize('update', User::class);

        if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {

            $user_raw_array = $request->input('ids');
            $update_array = array();
            $manager_conflict = false;
            $users = User::whereIn('id', $user_raw_array)->where('id', '!=', Auth::user()->id)->get();

            if ($request->filled('location_id')) {
                $update_array['location_id'] = $request->input('location_id');
            }
            if ($request->filled('department_id')) {
                $update_array['department_id'] = $request->input('department_id');
            }
            if ($request->filled('city')) {
                $update_array['city'] = $request->input('city');
            }

            if ($request->filled('company_id')) {
                $update_array['company_id'] = $request->input('company_id');
            }
            if ($request->filled('locale')) {
                $update_array['locale'] = $request->input('locale');
            }


            if ($request->filled('manager_id')) {

                // Do not allow a manager update if the selected manager is one of the users being
                // edited.
                if (!array_key_exists($request->input('manager_id'), $user_raw_array)) {
                    $update_array['manager_id'] = $request->input('manager_id');
                } else {
                    $manager_conflict = true;
                }

            }
            if ($request->filled('activated')) {
                $update_array['activated'] = $request->input('activated');
            }

            // Save the updated info
            if (count($update_array) > 0) {
                User::whereIn('id', $user_raw_array)->where('id', '!=', Auth::user()->id)->update($update_array);
            }

            // Only sync groups if groups were selected
            if ($request->filled('groups')) {
                foreach ($users as $user) {
                    $user->groups()->sync($request->input('groups'));
                }
            }

            if ($manager_conflict) {
                return redirect()->route('users.index')
                    ->with('warning', trans('admin/users/message.bulk_manager_warn'));
            }

            return redirect()->route('users.index')
                ->with('success', trans('admin/users/message.success.update_bulk'));
        }

        return redirect()->back()->with('error', 'No users selected');



    }

    /**
    * Soft-delete bulk users
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @return \Illuminate\Http\RedirectResponse
     */
    public function postBulkSave(Request $request)
    {
        $this->authorize('update', User::class);

        if ((!$request->filled('ids')) || (count($request->input('ids')) == 0)) {
            return redirect()->back()->with('error', 'No users selected');
        } elseif ((!$request->filled('status_id')) || ($request->input('status_id')=='')) {
            return redirect()->route('users.index')->with('error', 'No status selected');
        } else {

            $user_raw_array = Input::get('ids');
            $asset_array = array();

            if (($key = array_search(Auth::user()->id, $user_raw_array)) !== false) {
                unset($user_raw_array[$key]);
            }


            if (!config('app.lock_passwords')) {

                $users = User::whereIn('id', $user_raw_array)->get();
                $assets = Asset::whereIn('assigned_to', $user_raw_array)->get();
                $accessories = DB::table('accessories_users')->whereIn('assigned_to', $user_raw_array)->get();
                $licenses = DB::table('license_seats')->whereIn('assigned_to', $user_raw_array)->get();
                $license_array = array();
                $accessory_array = array();

                foreach ($assets as $asset) {

                    $asset_array[] = $asset->id;

                    // Update the asset log
                    $logAction = new Actionlog();
                    $logAction->item_id = $asset->id;
                    $logAction->item_type = Asset::class;
                    $logAction->target_id = $asset->assigned_to;
                    $logAction->target_type = User::class;
                    $logAction->user_id = Auth::user()->id;
                    $logAction->note = 'Bulk checkin asset and delete user';
                    $logAction->logaction('checkin from');

                    Asset::whereIn('id', $asset_array)->update([
                                'status_id' => e(Input::get('status_id')),
                                'assigned_to' => null,
                    ]);
                }

                foreach ($accessories as $accessory) {
                    $accessory_array[] = $accessory->accessory_id;
                    // Update the asset log
                    $logAction = new Actionlog();
                    $logAction->item_id = $accessory->id;
                    $logAction->item_type = Accessory::class;
                    $logAction->target_id = $accessory->assigned_to;
                    $logAction->target_type = User::class;
                    $logAction->user_id = Auth::user()->id;
                    $logAction->note = 'Bulk checkin accessory and delete user';
                    $logAction->logaction('checkin from');
                }

                foreach ($licenses as $license) {
                    $license_array[] = $license->id;
                    // Update the asset log
                    $logAction = new Actionlog();
                    $logAction->item_id = $license->id;
                    $logAction->item_type = License::class;
                    $logAction->target_id = $license->assigned_to;
                    $logAction->target_type = User::class;
                    $logAction->user_id = Auth::user()->id;
                    $logAction->note = 'Bulk checkin license and delete user';
                    $logAction->logaction('checkin from');
                }

                LicenseSeat::whereIn('id', $license_array)->update(['assigned_to' => null]);

                foreach ($users as $user) {
                    $user->accessories()->sync(array());
                    $user->delete();
                }

                return redirect()->route('users.index')->with('success', 'Your selected users have been deleted and their assets have been updated.');
            }
            return redirect()->route('users.index')->with('error', 'Bulk delete is not enabled in this installation');
        }
    }

    /**
    * Restore a deleted user
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @param  int  $id
    * @return \Illuminate\Http\RedirectResponse
     */
    public function getRestore($id = null)
    {
        $this->authorize('edit', User::class);
            // Get user information
        if (!$user = User::onlyTrashed()->find($id)) {
            return redirect()->route('users.index')->with('error', trans('admin/users/messages.user_not_found'));
        }

        // Restore the user
        if (User::withTrashed()->where('id', $id)->restore()) {
            return redirect()->route('users.index')->with('success', trans('admin/users/message.success.restored'));
        }
        return redirect()->route('users.index')->with('error', 'User could not be restored.');
    }


    /**
    * Return a view with user detail
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @param  int  $userId
    * @return \Illuminate\Contracts\View\View
     */
    public function show($userId = null)
    {
        if (!$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')
            ->withTrashed()
            ->find($userId))
        {

            return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
        }

        $userlog = $user->userlog->load('item');

        if (isset($user->id)) {
            $this->authorize('view', $user);
            return view('users/view', compact('user', 'userlog'));
        }
    }

    /**
    * Unsuspend a user.
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @param  int  $id
    * @return Redirect
    */
    public function getUnsuspend($id = null)
    {
        try {
            // Get user information
            $user = User::find($id);
            $this->authorize('edit', $user);

            // Check if we are not trying to unsuspend ourselves
            if ($user->id === Auth::user()->id) {
                // Prepare the error message
                $error = trans('admin/users/message.error.unsuspend');
                // Redirect to the user management page
                return redirect()->route('users.index')->with('error', $error);
            }

            // Do we have permission to unsuspend this user?
            if ($user->isSuperUser() && !Auth::user()->isSuperUser()) {
                // Redirect to the user management page
                return redirect()->route('users.index')->with('error', 'Insufficient permissions!');
            }

            // Prepare the success message
            $success = trans('admin/users/message.success.unsuspend');
            // Redirect to the user management page
            return redirect()->route('users.index')->with('success', $success);
        } catch (UserNotFoundException $e) {
            // Prepare the error message
            $error = trans('admin/users/message.user_not_found', compact('id'));
            // Redirect to the user management page
            return redirect()->route('users.index')->with('error', $error);
        }
    }


    /**
    * Return a view containing a pre-populated new user form,
    * populated with some fields from an existing user.
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.0]
    * @param  int  $id
    * @return \Illuminate\Contracts\View\View
     */
    public function getClone($id = null)
    {
        $this->authorize('create', User::class);
        // We need to reverse the UI specific logic for our
        // permissions here before we update the user.
        $permissions = Input::get('permissions', array());
        //$this->decodePermissions($permissions);
        app('request')->request->set('permissions', $permissions);


        try {
            // Get the user information
            $user_to_clone = User::withTrashed()->find($id);
            $user = clone $user_to_clone;
            $user->first_name = '';
            $user->last_name = '';
            $user->email = substr($user->email, ($pos = strpos($user->email, '@')) !== false ? $pos : 0);

            $user->id = null;

            // Get this user groups
            $userGroups = $user_to_clone->groups()->pluck('name', 'id');
            // Get all the available permissions
            $permissions = config('permissions');
            $clonedPermissions = $user_to_clone->decodePermissions();

            $userPermissions =Helper::selectedPermissionsArray($permissions, $clonedPermissions);

            // Show the page
            return view('users/edit', compact('permissions', 'userPermissions'))
                            ->with('user', $user)
                            ->with('groups', Group::pluck('name', 'id'))
                            ->with('userGroups', $userGroups)
                            ->with('clone_user', $user_to_clone);
        } catch (UserNotFoundException $e) {

            return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found'));
        }
    }

    /**
     * Return JSON response with a list of user details for the getIndex() view.
     *
     * @author [A. Gianotto] [<snipe@snipe.net>]
     * @since [v1.6]
     * @param AssetFileRequest $request
     * @param int $userId
     * @return string JSON
     */
    public function postUpload(AssetFileRequest $request, $userId = null)
    {

        $user = User::find($userId);
        $destinationPath = config('app.private_uploads') . '/users';

        if (isset($user->id)) {
            $this->authorize('update', $user);

            if (!$request->has('file')) {
                \Log::debug('No file selected: ');
                \Log::debug(print_r($request, true));
                return redirect()->back()->with('error', 'No file submitted.');

            } else {
                foreach ($request->file('file') as $file) {

                    $extension = $file->getClientOriginalExtension();
                    $filename = 'user-' . $user->id . '-' . str_random(8);
                    $filename .= '-' . str_slug($file->getClientOriginalName()) . '.' . $extension;
                    $upload_success = $file->move($destinationPath, $filename);

                    //Log the uploaded file to the log
                    $logAction = new Actionlog();
                    $logAction->item_id = $user->id;
                    $logAction->item_type = User::class;
                    $logAction->target_type = User::class;
                    $logAction->target_id = $user->id;
                    $logAction->user_id = Auth::user()->id;
                    $logAction->note = $request->input('notes');
                    $logAction->created_at = date("Y-m-d H:i:s");
                    $logAction->filename = $filename;
                    $logAction->action_type = 'uploaded';
                    $logAction->save();

                }
                return redirect()->back()->with('success', 'File uploaded');
            }

        }
        return redirect()->route('users.index')->with('error', 'Error uploading files');
    }


    /**
    * Delete file
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.6]
    * @param  int  $userId
    * @param  int  $fileId
    * @return \Illuminate\Http\RedirectResponse
     */
    public function getDeleteFile($userId = null, $fileId = null)
    {
        $user = User::find($userId);
        $destinationPath = config('app.private_uploads').'/users';

        if (isset($user->id)) {
            $this->authorize('update', $user);
            $log = Actionlog::find($fileId);
            $full_filename = $destinationPath . '/' . $log->filename;
            if (file_exists($full_filename)) {
                unlink($destinationPath . '/' . $log->filename);
            }
            $log->delete();
            return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
        }

        return redirect()->route('users.index')->with('error', trans('admin/users/message.does_not_exist'));

    }

    /**
    * Display/download the uploaded file
    *
    * @author [A. Gianotto] [<snipe@snipe.net>]
    * @since [v1.6]
    * @param  int  $userId
    * @param  int  $fileId
    * @return mixed
    */
    public function displayFile($userId = null, $fileId = null)
    {
        $user = User::find($userId);

        // the license is valid
        if (isset($user->id)) {
            $this->authorize('view', $user);

            $log = Actionlog::find($fileId);
            $file = $log->get_src('users');
            return Response::download($file);
        }
        // Prepare the error message
        $error = trans('admin/users/message.does_not_exist', compact('id'));

        // Redirect to the licence management page
        return redirect()->route('users.index')->with('error', $error);
    }

    /**
    * Return view for LDAP import
    *
    * @author Aladin Alaily
    * @since [v1.8]
    * @return \Illuminate\Contracts\View\View
     */
    public function getLDAP()
    {
        $this->authorize('update', User::class);
        try {
            $ldapconn = Ldap::connectToLdap();
        } catch (\Exception $e) {
            return redirect()->route('users.index')->with('error', $e->getMessage());
        }

        try {
            Ldap::bindAdminToLdap($ldapconn);
        } catch (\Exception $e) {
            return redirect()->route('users.index')->with('error', $e->getMessage());
        }

        return view('users/ldap');
    }


    /**
    * Declare the rules for the ldap fields validation.
    *
    * @author Aladin Alaily
    * @since [v1.8]
    * @var array
    * @deprecated 3.0
    * @todo remove this method in favor of other validation
    * @var array
    */

    protected $ldapValidationRules = array(
        'firstname' => 'required|string|min:2',
        'employee_number' => 'string',
        'username' => 'required|min:2|unique:users,username',
        'email' => 'email|unique:users,email',
    );

    /**
    * LDAP form processing.
    *
    * @author Aladin Alaily
    * @since [v1.8]
    * @return \Illuminate\Http\RedirectResponse
     */
    public function postLDAP(Request $request)
    {
        // Call Artisan LDAP import command.
        $location_id = $request->input('location_id');
        Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]);

        // Collect and parse JSON summary.
        $ldap_results_json = Artisan::output();
        $ldap_results = json_decode($ldap_results_json, true);

        // Direct user to appropriate status page.
        if ($ldap_results['error']) {
            return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
        } else {
            return redirect()->route('ldap/user')->with('success', "LDAP Import successful.")->with('summary', $ldap_results['summary']);
        }
    }
    

    /**
     * Exports users to CSV
     *
     * @author [A. Gianotto] [<snipe@snipe.net>]
     * @since [v3.5]
     * @return StreamedResponse
     */
    public function getExportUserCsv()
    {

        $this->authorize('view', User::class);
        \Debugbar::disable();

        $response = new StreamedResponse(function () {
            // Open output stream
            $handle = fopen('php://output', 'w');

            User::with('assets', 'accessories', 'consumables', 'department', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle')->orderBy('created_at', 'DESC')->chunk(500, function($users) use($handle) {
                $headers=[
                    // strtolower to prevent Excel from trying to open it as a SYLK file
                    strtolower(trans('general.id')),
                    trans('admin/companies/table.title'),
                    trans('admin/users/table.title'),
                    trans('admin/users/table.employee_num'),
                    trans('admin/users/table.name'),
                    trans('admin/users/table.username'),
                    trans('admin/users/table.email'),
                    trans('admin/users/table.manager'),
                    trans('admin/users/table.location'),
                    trans('general.department'),
                    trans('general.assets'),
                    trans('general.licenses'),
                    trans('general.accessories'),
                    trans('general.consumables'),
                    trans('admin/users/table.groups'),
                    trans('general.notes'),
                    trans('admin/users/table.activated'),
                    trans('general.created_at')
                ];

                fputcsv($handle, $headers);

                foreach ($users as $user) {
                    $user_groups = '';

                    foreach ($user->groups as $user_group) {
                        $user_groups .= $user_group->name.', ';
                    }

                    // Add a new row with data
                    $values = [
                        $user->id,
                        ($user->company) ? $user->company->name : '',
                        $user->jobtitle,
                        $user->employee_num,
                        $user->present()->fullName(),
                        $user->username,
                        $user->email,
                        ($user->manager) ? $user->manager->present()->fullName() : '',
                        ($user->userloc) ? $user->userloc->name : '',
                        ($user->department) ? $user->department->name : '',
                        $user->assets->count(),
                        $user->licenses->count(),
                        $user->accessories->count(),
                        $user->consumables->count(),
                        $user_groups,
                        $user->notes,
                        ($user->activated=='1') ?  trans('general.yes') : trans('general.no'),
                        $user->created_at,

                    ];

                    fputcsv($handle, $values);
                }
            });

            // Close the output stream
            fclose($handle);
        }, 200, [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="users-'.date('Y-m-d-his').'.csv"',
        ]);

        return $response;

    }

    /**
     * LDAP form processing.
     *
     * @author Aladin Alaily
     * @since [v1.8]
     * @return \Illuminate\Http\RedirectResponse
     */
    public function printInventory($id)
    {
        $this->authorize('view', User::class);
        $show_user = User::where('id',$id)->withTrashed()->first();
        $assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get();
        $licenses = $show_user->licenses()->get();
        $accessories = $show_user->accessories()->get();
        $consumables = $show_user->consumables()->get();
        return view('users/print')->with('assets', $assets)->with('licenses',$licenses)->with('accessories', $accessories)->with('consumables', $consumables)->with('show_user', $show_user);

    }

}